From 619bddb1e32cf9b5f230d045f698450109167c60 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 8 May 2025 01:05:16 -0700 Subject: [PATCH 01/83] add xform --- gnovm/cmd/gno/tool_lint.go | 23 +++++++++- gnovm/pkg/gnolang/gotypecheck.go | 77 ++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index d772f877403..4e77d985841 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -167,7 +167,28 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { // Check test files packageFiles := sourceAndTestFileset(memPkg) - tm.PreprocessFiles(memPkg.Name, pkgPath, packageFiles, false, false) + pn, _ := tm.PreprocessFiles(memPkg.Name, memPkg.Path, packageFiles, false, false) + + // Use the preprocessor to collect the transformations needed to be done. + // They are collected in pn.GetAttribute("XREALMITEM") + for _, fn := range packageFiles.Files { + gno.FindXRealmItems(gs, pn, fn) + } + + if xform, ok := pn.GetAttribute("XREALMITEM").(map[string]string); ok { + tcErr := gno.TypeCheckMemPackage2(memPkg, gs, true, true, xform) + if tcErr != nil { + //panic(fmt.Sprintf("oops %v", tcErr)) + for _, file := range memPkg.Files { + fmt.Println("FORMATTED:", file.Name, file.Body) + } + } else { + for _, file := range memPkg.Files { + fmt.Println("FORMATTED:", file.Name, file.Body) + } + // fmt.Println("NO tcErr") + } + } }) if hasRuntimeErr { hasError = true diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index e34c5a547b8..a4d418ca19b 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -2,6 +2,7 @@ package gnolang import ( "bytes" + "errors" "fmt" "go/ast" "go/format" @@ -14,6 +15,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" + "golang.org/x/tools/go/ast/astutil" ) // type checking (using go/types) @@ -32,7 +34,7 @@ type MemPackageGetter interface { // If format is true, the code in msmpkg will be automatically updated with the // formatted source code. func TypeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, format bool) error { - return typeCheckMemPackage(mempkg, getter, false, format) + return typeCheckMemPackage(mempkg, getter, false, format, nil) } // TypeCheckMemPackageTest performs the same type checks as [TypeCheckMemPackage], @@ -57,7 +59,7 @@ func typeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, testin } imp.cfg.Importer = imp - _, err := imp.parseCheckMemPackage(mempkg, format) + _, err := imp.parseCheckMemPackage(mempkg, format, xform) // prefer to return errs instead of err: // err will generally contain only the first error encountered. if errs != nil { @@ -102,7 +104,7 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac return nil, err } fmt_ := false - result, err := g.parseCheckMemPackage(mpkg, fmt_) + result, err := g.parseCheckMemPackage(mpkg, fmt_, nil) g.cache[path] = gnoImporterResult{pkg: result, err: err} return result, err } @@ -146,7 +148,7 @@ func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt_ bool) (*ty // Enforce formatting. // This must happen before logical transforms. - if fmt_ { + if fmt_ && xform == nil { var buf bytes.Buffer err = format.Node(&buf, fset, f) if err != nil { @@ -169,6 +171,22 @@ func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt_ bool) (*ty } */ + if xform != nil { + // transform for interrealm spec 2 + if err := transformCrossing(mpkg.Path, fset, file.Name, f, xform); err != nil { + errs = multierr.Append(errs, err) + continue + } + var buf bytes.Buffer + err = format.Node(&buf, fset, f) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + file.Body = buf.String() + // fmt.Println("FORMATTED") XXX + } + files = append(files, f) } if errs != nil { @@ -184,6 +202,8 @@ func istypednil(x any) bool { return false } // shim func crossing() { } // shim func cross[F any](fn F) F { return fn } // shim func revive[F any](fn F) any { return nil } // shim +type realm struct{} // shim +// var nilrealm realm // shim `, mpkg.Name), } f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) @@ -250,3 +270,52 @@ func filterCrossing(f *ast.File) (err error) { return err } */ + +func transformCrossing(pkgPath string, fs *token.FileSet, fileName string, f *ast.File, xform map[string]string) (err error) { + astutil.Apply(f, nil, func(c *astutil.Cursor) bool { + switch n := c.Node().(type) { + case *ast.ExprStmt: + if ce, ok := n.X.(*ast.CallExpr); ok { + if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { + // Validate syntax. + if len(ce.Args) != 0 { + err = errors.New("crossing called with non empty parameters") + } + // Delete statement 'crossing()'. + c.Delete() + // XXX how do you remove the newline after crossing()? + } + } + case *ast.FuncDecl: + pos := n.Pos() + posn := fs.Position(pos) + l, c := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, l, c) + if xform[key] == "add curfunc" { + n.Type.Params.List = append([]*ast.Field{&ast.Field{ + Names: []*ast.Ident{ast.NewIdent("cur")}, + Type: ast.NewIdent("realm"), + }}, n.Type.Params.List...) + } + case *ast.CallExpr: + pos := n.Pos() + posn := fs.Position(pos) + l, c := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, l, c) + if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { + // Skip these. + // Gno AST doesn't store the end location, only the start. + // cross(x)(...) and cross(x) have the same start. + return true + } + //fmt.Println("AST APPLY CALLEXPR", key, n) + if xform[key] == "add curcall" { + n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) + } else if xform[key] == "add nilrealm" { + // n.Args = append([]ast.Expr{ast.NewIdent("nilrealm")}, n.Args...) + } + } + return true + }) + return err +} From b6a4de831929da4ecda20dd72945900334c964b7 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 8 May 2025 01:29:08 -0700 Subject: [PATCH 02/83] add preprocess2 and hack lint --- gnovm/cmd/gno/tool_lint.go | 89 ++++++++++++++++++- gnovm/pkg/gnolang/preprocess2.go | 148 +++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 gnovm/pkg/gnolang/preprocess2.go diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 4e77d985841..86e2b4b2270 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -8,6 +8,7 @@ import ( "go/scanner" "go/types" goio "io" + "io/ioutil" "os" "path/filepath" "regexp" @@ -102,6 +103,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { test.StoreOptions{PreprocessOnly: true}, ) + pns := map[string]*gno.PackageNode{} + for _, dirPath := range dirPaths { if verbose { io.ErrPrintln(dirPath) @@ -168,10 +171,84 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { packageFiles := sourceAndTestFileset(memPkg) pn, _ := tm.PreprocessFiles(memPkg.Name, memPkg.Path, packageFiles, false, false) + pns[memPkg.Path] = pn + }) + if hasRuntimeErr { + hasError = true + } + } + + for _, dirPath := range dirPaths { + if verbose { + io.ErrPrintln(dirPath) + } + + info, err := os.Stat(dirPath) + if err == nil && !info.IsDir() { + dirPath = filepath.Dir(dirPath) + } + + // Check if 'gno.mod' exists + gmFile, err := gnomod.ParseAt(dirPath) + if err != nil { + issue := lintIssue{ + Code: lintGnoMod, + Confidence: 1, + Location: dirPath, + Msg: err.Error(), + } + io.ErrPrintln(issue) + hasError = true + } + + pkgPath, _ := determinePkgPath(gmFile, dirPath, cfg.rootDir) + memPkg, err := gno.ReadMemPackage(dirPath, pkgPath) + if err != nil { + io.ErrPrintln(issueFromError(dirPath, err).String()) + hasError = true + continue + } + + // Perform imports using the parent store. + if err := test.LoadImports(ts, memPkg); err != nil { + io.ErrPrintln(issueFromError(dirPath, err).String()) + hasError = true + continue + } + + // Handle runtime errors + hasRuntimeErr := catchRuntimeError(dirPath, io.Err(), func() { + // Wrap in cache wrap so execution of the linter doesn't impact + // other packages. + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + + // Run type checking + if gmFile == nil || !gmFile.Draft { + foundErr, err := lintTypeCheck(io, memPkg, gs) + if err != nil { + io.ErrPrintln(err) + hasError = true + } else if foundErr { + hasError = true + } + } else if verbose { + io.ErrPrintfln("%s: module is draft, skipping type check", dirPath) + } + + tm := test.Machine(gs, goio.Discard, memPkg.Path, false) + + defer tm.Release() + + // Check test files + packageFiles := sourceAndTestFileset(memPkg) + + pn := pns[memPkg.Path] // Use the preprocessor to collect the transformations needed to be done. // They are collected in pn.GetAttribute("XREALMITEM") for _, fn := range packageFiles.Files { + fmt.Println("PROCESS", fn.Name) gno.FindXRealmItems(gs, pn, fn) } @@ -180,11 +257,21 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { if tcErr != nil { //panic(fmt.Sprintf("oops %v", tcErr)) for _, file := range memPkg.Files { - fmt.Println("FORMATTED:", file.Name, file.Body) + fmt.Println("FORMATTED:", file.Name) // , file.Body) + fpath := filepath.Join(dirPath, file.Name) + err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) + if err != nil { + panic(err) + } } } else { for _, file := range memPkg.Files { fmt.Println("FORMATTED:", file.Name, file.Body) + fpath := filepath.Join(dirPath, file.Name) + err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) + if err != nil { + panic(err) + } } // fmt.Println("NO tcErr") } diff --git a/gnovm/pkg/gnolang/preprocess2.go b/gnovm/pkg/gnolang/preprocess2.go new file mode 100644 index 00000000000..d95aa7548a7 --- /dev/null +++ b/gnovm/pkg/gnolang/preprocess2.go @@ -0,0 +1,148 @@ +package gnolang + +import ( + "fmt" + "reflect" +) + +type XRealmItem struct { + Type string + Location +} + +// t: type, p: pkgpath, f: filename, l: line, c: column +func addXRealmItem(n Node, t string, p string, f string, l int, c int) { + x, _ := n.GetAttribute("XREALMITEM").(map[string]string) // p/f:l:c -> t + if x == nil { + x = make(map[string]string) + n.SetAttribute("XREALMITEM", x) + } + key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) + x[key] = t +} + +// Finds XRealmItems for interream spec 2 transpiling tool. +// Sets to bn attribute XREALMITEM. +func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { + if pn != packageOf(bn) { + panic("package mismatch") + } + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = pn + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("FindXRealmItems %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_LEAVE: + + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case *CallExpr: + if _, ok := n.Func.(*constTypeExpr); ok { + return n, TRANS_CONTINUE + } else if cx, ok := n.Func.(*ConstExpr); ok { + if cx.TypedValue.T.Kind() != FuncKind { + return n, TRANS_CONTINUE + } + fv := cx.GetFunc() + if fv.PkgPath == uversePkgPath && fv.Name == "cross" { + // XXX Add a 'nilrealm' as first argument. + // This is not part of the proposed spec, + // but Go doesn't support generic cross[T any]()T + // that curries the first `cur realm` argument. + // Gno2 can simply omit the `nilrealm` argument. + pc, ok := ns[len(ns)-1].(*CallExpr) + if !ok { + panic("cross(fn) must be followed by a call") + } + loc := last.GetLocation() + // fmt.Printf("add nilrealm: %s/%s:%d:%d\n", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + addXRealmItem(pn, "add nilrealm", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { + if !IsRealmPath(pn.PkgPath) { + panic("crossing() is only allowed in realm packages") + } + // XXX Add `cur realm` as first argument to func decl. + loc := last.GetLocation() + // fmt.Printf("add curfunc: %s/%s:%d:%d\n", loc.PkgPath, loc.File, loc.Line, loc.Column) + addXRealmItem(pn, "add curfunc", loc.PkgPath, loc.File, loc.Line, loc.Column) + } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { + // reserve attach() so we can support it later. + panic("attach() not yet supported") + } + } else { + // Already handled, added "add nilrealm" + // from the "cross" case above. + if n.WithCross { + // Is a cross(fn)(...) call. + // Leave it alone. + return n, TRANS_CONTINUE + } + pv := pn.NewPackage() // temporary + store := store.BeginTransaction(nil, nil, nil) + store.SetCachePackage(pv) + m := NewMachine("x", store) + defer m.Release() + tv := TypedValue{} + func() { + // cannot be resolved statically + defer func() { + recover() + // fmt.Println("FAILED TO EVALSTATIC", n.Func) + }() + // try to evaluate n.Func. + tv = m.EvalStatic(last, n.Func) + }() + switch cv := tv.V.(type) { + case nil: + return n, TRANS_CONTINUE + case TypeValue: + panic("wtf") + case *FuncValue: + if cv.IsCrossing() { + // XXX Not cross-called, so add `cur` as first argument. + loc := last.GetLocation() + // fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + } + case *BoundMethodValue: + if cv.IsCrossing() { + // XXX Not cross-called, so add `cur` as first argument. + loc := last.GetLocation() + // fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + } + } + } + } + // end type switch statement + // END TRANS_LEAVE ----------------------- + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} From dc00ab62e2800fb44497e3caa98462a9c846190c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 8 May 2025 09:19:06 -0700 Subject: [PATCH 03/83] ... --- gnovm/cmd/gno/tool_lint.go | 145 ++++++++++++++++++------------- gnovm/pkg/gnolang/preprocess2.go | 18 ++-- 2 files changed, 93 insertions(+), 70 deletions(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 86e2b4b2270..1b300b7e1bb 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -23,6 +23,11 @@ import ( "go.uber.org/multierr" ) +type processedPackage struct { + pn *gno.PackageNode + fset *gno.FileSet +} + type lintCfg struct { verbose bool rootDir string @@ -103,7 +108,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { test.StoreOptions{PreprocessOnly: true}, ) - pns := map[string]*gno.PackageNode{} + pns := map[string]processedPackage{} for _, dirPath := range dirPaths { if verbose { @@ -171,7 +176,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { packageFiles := sourceAndTestFileset(memPkg) pn, _ := tm.PreprocessFiles(memPkg.Name, memPkg.Path, packageFiles, false, false) - pns[memPkg.Path] = pn + pns[memPkg.Path] = processedPackage{pn, packageFiles} }) if hasRuntimeErr { hasError = true @@ -209,76 +214,94 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { continue } - // Perform imports using the parent store. - if err := test.LoadImports(ts, memPkg); err != nil { - io.ErrPrintln(issueFromError(dirPath, err).String()) - hasError = true - continue - } + // Wrap in cache wrap so execution of the linter doesn't impact + // other packages. + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) - // Handle runtime errors - hasRuntimeErr := catchRuntimeError(dirPath, io.Err(), func() { - // Wrap in cache wrap so execution of the linter doesn't impact - // other packages. - cw := bs.CacheWrap() - gs := ts.BeginTransaction(cw, cw, nil) - - // Run type checking - if gmFile == nil || !gmFile.Draft { - foundErr, err := lintTypeCheck(io, memPkg, gs) - if err != nil { - io.ErrPrintln(err) - hasError = true - } else if foundErr { - hasError = true - } - } else if verbose { - io.ErrPrintfln("%s: module is draft, skipping type check", dirPath) - } + // Check test files + ppkg, ok := pns[memPkg.Path] + if !ok { + panic("where did it go") + } + pn, packageFiles := ppkg.pn, ppkg.fset + fmt.Println("PN", memPkg.Path, pn) + + // Use the preprocessor to collect the transformations needed to be done. + // They are collected in pn.GetAttribute("XREALMITEM") + for _, fn := range packageFiles.Files { + fmt.Println("PROCESS", fn.Name) + gno.FindXRealmItems(gs, pn, fn) + } + } - tm := test.Machine(gs, goio.Discard, memPkg.Path, false) + for _, dirPath := range dirPaths { + if verbose { + io.ErrPrintln(dirPath) + } - defer tm.Release() + info, err := os.Stat(dirPath) + if err == nil && !info.IsDir() { + dirPath = filepath.Dir(dirPath) + } - // Check test files - packageFiles := sourceAndTestFileset(memPkg) + // Check if 'gno.mod' exists + gmFile, err := gnomod.ParseAt(dirPath) + if err != nil { + issue := lintIssue{ + Code: lintGnoMod, + Confidence: 1, + Location: dirPath, + Msg: err.Error(), + } + io.ErrPrintln(issue) + hasError = true + } - pn := pns[memPkg.Path] + pkgPath, _ := determinePkgPath(gmFile, dirPath, cfg.rootDir) + memPkg, err := gno.ReadMemPackage(dirPath, pkgPath) + if err != nil { + io.ErrPrintln(issueFromError(dirPath, err).String()) + hasError = true + continue + } - // Use the preprocessor to collect the transformations needed to be done. - // They are collected in pn.GetAttribute("XREALMITEM") - for _, fn := range packageFiles.Files { - fmt.Println("PROCESS", fn.Name) - gno.FindXRealmItems(gs, pn, fn) - } + // Wrap in cache wrap so execution of the linter doesn't impact + // other packages. + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) - if xform, ok := pn.GetAttribute("XREALMITEM").(map[string]string); ok { - tcErr := gno.TypeCheckMemPackage2(memPkg, gs, true, true, xform) - if tcErr != nil { - //panic(fmt.Sprintf("oops %v", tcErr)) - for _, file := range memPkg.Files { - fmt.Println("FORMATTED:", file.Name) // , file.Body) - fpath := filepath.Join(dirPath, file.Name) - err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) - if err != nil { - panic(err) - } + // Check test files + ppkg, ok := pns[memPkg.Path] + if !ok { + panic("where did it go") + } + pn, _ := ppkg.pn, ppkg.fset + fmt.Println("PN", memPkg.Path, pn) + if xform, ok := pn.GetAttribute("XREALMITEM").(map[string]string); ok { + fmt.Println("UM") + tcErr := gno.TypeCheckMemPackage2(memPkg, gs, true, true, xform) + if tcErr != nil { + //panic(fmt.Sprintf("oops %v", tcErr)) + for _, file := range memPkg.Files { + fmt.Println("FORMATTED:", file.Name) // , file.Body) + fpath := filepath.Join(dirPath, file.Name) + err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) + if err != nil { + panic(err) } - } else { - for _, file := range memPkg.Files { - fmt.Println("FORMATTED:", file.Name, file.Body) - fpath := filepath.Join(dirPath, file.Name) - err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) - if err != nil { - panic(err) - } + } + } else { + for _, file := range memPkg.Files { + fmt.Println("FORMATTED:", file.Name, file.Body) + fpath := filepath.Join(dirPath, file.Name) + err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) + if err != nil { + panic(err) } - // fmt.Println("NO tcErr") } + // fmt.Println("NO tcErr") } - }) - if hasRuntimeErr { - hasError = true } } diff --git a/gnovm/pkg/gnolang/preprocess2.go b/gnovm/pkg/gnolang/preprocess2.go index d95aa7548a7..9dd15b5c918 100644 --- a/gnovm/pkg/gnolang/preprocess2.go +++ b/gnovm/pkg/gnolang/preprocess2.go @@ -24,9 +24,6 @@ func addXRealmItem(n Node, t string, p string, f string, l int, c int) { // Finds XRealmItems for interream spec 2 transpiling tool. // Sets to bn attribute XREALMITEM. func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { - if pn != packageOf(bn) { - panic("package mismatch") - } // create stack of BlockNodes. var stack []BlockNode = make([]BlockNode, 0, 32) var last BlockNode = pn @@ -47,7 +44,6 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { // ---------------------------------------- case TRANS_LEAVE: - // Pop block from stack. // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR @@ -63,8 +59,10 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { switch n := n.(type) { case *CallExpr: if _, ok := n.Func.(*constTypeExpr); ok { + fmt.Println("CONOST1", n) return n, TRANS_CONTINUE } else if cx, ok := n.Func.(*ConstExpr); ok { + fmt.Println("CONOST2", n) if cx.TypedValue.T.Kind() != FuncKind { return n, TRANS_CONTINUE } @@ -80,7 +78,7 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { panic("cross(fn) must be followed by a call") } loc := last.GetLocation() - // fmt.Printf("add nilrealm: %s/%s:%d:%d\n", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + fmt.Printf("add nilrealm: %s/%s:%d:%d\n", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) addXRealmItem(pn, "add nilrealm", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { if !IsRealmPath(pn.PkgPath) { @@ -88,16 +86,18 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { } // XXX Add `cur realm` as first argument to func decl. loc := last.GetLocation() - // fmt.Printf("add curfunc: %s/%s:%d:%d\n", loc.PkgPath, loc.File, loc.Line, loc.Column) + fmt.Printf("add curfunc: %s/%s:%d:%d\n", loc.PkgPath, loc.File, loc.Line, loc.Column) addXRealmItem(pn, "add curfunc", loc.PkgPath, loc.File, loc.Line, loc.Column) } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { // reserve attach() so we can support it later. panic("attach() not yet supported") } } else { + fmt.Println("CONOST3", n) // Already handled, added "add nilrealm" // from the "cross" case above. if n.WithCross { + fmt.Println("CONOST4", n) // Is a cross(fn)(...) call. // Leave it alone. return n, TRANS_CONTINUE @@ -112,7 +112,7 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { // cannot be resolved statically defer func() { recover() - // fmt.Println("FAILED TO EVALSTATIC", n.Func) + //fmt.Println("FAILED TO EVALSTATIC", n.Func, r) }() // try to evaluate n.Func. tv = m.EvalStatic(last, n.Func) @@ -126,14 +126,14 @@ func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { if cv.IsCrossing() { // XXX Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - // fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) } case *BoundMethodValue: if cv.IsCrossing() { // XXX Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - // fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) } } From cc0842f1592ce52eac4444f6e3ac8142efc84142 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 8 May 2025 16:50:37 -0700 Subject: [PATCH 04/83] refactor --- gnovm/cmd/gno/tool_lint.go | 205 ++++------------ gnovm/pkg/gnolang/gotypecheck.go | 136 ++--------- gnovm/pkg/gnolang/preprocess2.go | 148 ------------ gnovm/pkg/gnolang/transpile_gno0p9.go | 332 ++++++++++++++++++++++++++ gnovm/pkg/gnolang/uverse.go | 45 ++++ tm2/pkg/std/memfile.go | 66 +++-- 6 files changed, 486 insertions(+), 446 deletions(-) delete mode 100644 gnovm/pkg/gnolang/preprocess2.go create mode 100644 gnovm/pkg/gnolang/transpile_gno0p9.go diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 1b300b7e1bb..6f75dfb04f4 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -8,7 +8,6 @@ import ( "go/scanner" "go/types" goio "io" - "io/ioutil" "os" "path/filepath" "regexp" @@ -24,8 +23,9 @@ import ( ) type processedPackage struct { - pn *gno.PackageNode + mpkg *std.MemPackage fset *gno.FileSet + pn *gno.PackageNode } type lintCfg struct { @@ -96,7 +96,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - dirPaths, err := gnoPackagesFromArgsRecursively(args) + dirs, err := gnoPackagesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } @@ -108,48 +108,50 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { test.StoreOptions{PreprocessOnly: true}, ) - pns := map[string]processedPackage{} + ppkgs := map[string]processedPackage{} - for _, dirPath := range dirPaths { + //---------------------------------------- + // STEP 1: PREPROCESS ALL FILES + for _, dir := range dirs { if verbose { - io.ErrPrintln(dirPath) + io.ErrPrintln(dir) } - info, err := os.Stat(dirPath) + info, err := os.Stat(dir) if err == nil && !info.IsDir() { - dirPath = filepath.Dir(dirPath) + dir = filepath.Dir(dir) } // Check if 'gno.mod' exists - gmFile, err := gnomod.ParseAt(dirPath) + gmFile, err := gnomod.ParseAt(dir) if err != nil { issue := lintIssue{ Code: lintGnoMod, Confidence: 1, - Location: dirPath, + Location: dir, Msg: err.Error(), } io.ErrPrintln(issue) hasError = true } - pkgPath, _ := determinePkgPath(gmFile, dirPath, cfg.rootDir) - memPkg, err := gno.ReadMemPackage(dirPath, pkgPath) + pkgPath, _ := determinePkgPath(gmFile, dir, cfg.rootDir) + mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { - io.ErrPrintln(issueFromError(dirPath, pkgPath, err).String()) + io.ErrPrintln(issueFromError(dir, pkgPath, err).String()) hasError = true continue } // Perform imports using the parent store. - if err := test.LoadImports(ts, memPkg); err != nil { - io.ErrPrintln(issueFromError(dirPath, pkgPath, err).String()) + if err := test.LoadImports(ts, mpkg); err != nil { + io.ErrPrintln(issueFromError(dir, pkgPath, err).String()) hasError = true continue } // Handle runtime errors - hasRuntimeErr := catchRuntimeError(dirPath, pkgPath, io.Err(), func() { + hasRuntimeErr := catchRuntimeError(dir, pkgPath, io.Err(), func() { // Wrap in cache wrap so execution of the linter doesn't impact // other packages. cw := bs.CacheWrap() @@ -157,7 +159,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { // Run type checking if gmFile == nil || !gmFile.Draft { - foundErr, err := lintTypeCheck(io, dirPath, memPkg, gs) + foundErr, err := lintTypeCheck(io, dir, mpkg, gs) if err != nil { io.ErrPrintln(err) hasError = true @@ -165,7 +167,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { hasError = true } } else if verbose { - io.ErrPrintfln("%s: module is draft, skipping type check", dirPath) + io.ErrPrintfln("%s: module is draft, skipping type check", dir) } tm := test.Machine(gs, goio.Discard, pkgPath, false) @@ -173,135 +175,34 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { defer tm.Release() // Check test files - packageFiles := sourceAndTestFileset(memPkg) + packageFiles := sourceAndTestFileset(mpkg) - pn, _ := tm.PreprocessFiles(memPkg.Name, memPkg.Path, packageFiles, false, false) - pns[memPkg.Path] = processedPackage{pn, packageFiles} + pn, _ := tm.PreprocessFiles(mpkg.Name, mpkg.Path, packageFiles, false, false) + ppkgs[mpkg.Path] = processedPackage{mpkg, packageFiles, pn} + + // Use the preprocessor to collect the transformations needed to be done. + // They are collected in pn.GetAttribute("XREALMITEM") + for _, fn := range packageFiles.Files { + gno.FindGno0p9XItems(gs, pn, fn) + } }) if hasRuntimeErr { hasError = true } } - for _, dirPath := range dirPaths { - if verbose { - io.ErrPrintln(dirPath) - } - - info, err := os.Stat(dirPath) - if err == nil && !info.IsDir() { - dirPath = filepath.Dir(dirPath) - } - - // Check if 'gno.mod' exists - gmFile, err := gnomod.ParseAt(dirPath) - if err != nil { - issue := lintIssue{ - Code: lintGnoMod, - Confidence: 1, - Location: dirPath, - Msg: err.Error(), - } - io.ErrPrintln(issue) - hasError = true - } - - pkgPath, _ := determinePkgPath(gmFile, dirPath, cfg.rootDir) - memPkg, err := gno.ReadMemPackage(dirPath, pkgPath) - if err != nil { - io.ErrPrintln(issueFromError(dirPath, err).String()) - hasError = true - continue - } - - // Wrap in cache wrap so execution of the linter doesn't impact - // other packages. - cw := bs.CacheWrap() - gs := ts.BeginTransaction(cw, cw, nil) - - // Check test files - ppkg, ok := pns[memPkg.Path] + //---------------------------------------- + // STEP 2: TRANSFORM FOR Gno 0.9 + for _, dir := range dirs { + ppkg, ok := ppkgs[dir] if !ok { panic("where did it go") } - pn, packageFiles := ppkg.pn, ppkg.fset - fmt.Println("PN", memPkg.Path, pn) - - // Use the preprocessor to collect the transformations needed to be done. - // They are collected in pn.GetAttribute("XREALMITEM") - for _, fn := range packageFiles.Files { - fmt.Println("PROCESS", fn.Name) - gno.FindXRealmItems(gs, pn, fn) - } - } - - for _, dirPath := range dirPaths { - if verbose { - io.ErrPrintln(dirPath) - } - - info, err := os.Stat(dirPath) - if err == nil && !info.IsDir() { - dirPath = filepath.Dir(dirPath) - } - - // Check if 'gno.mod' exists - gmFile, err := gnomod.ParseAt(dirPath) - if err != nil { - issue := lintIssue{ - Code: lintGnoMod, - Confidence: 1, - Location: dirPath, - Msg: err.Error(), - } - io.ErrPrintln(issue) - hasError = true - } - - pkgPath, _ := determinePkgPath(gmFile, dirPath, cfg.rootDir) - memPkg, err := gno.ReadMemPackage(dirPath, pkgPath) + mpkg, pn := ppkg.mpkg, ppkg.pn + xform := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) + err := gno.TranspileToGno0p9(mpkg, dir, true, true, xform) if err != nil { - io.ErrPrintln(issueFromError(dirPath, err).String()) - hasError = true - continue - } - - // Wrap in cache wrap so execution of the linter doesn't impact - // other packages. - cw := bs.CacheWrap() - gs := ts.BeginTransaction(cw, cw, nil) - - // Check test files - ppkg, ok := pns[memPkg.Path] - if !ok { - panic("where did it go") - } - pn, _ := ppkg.pn, ppkg.fset - fmt.Println("PN", memPkg.Path, pn) - if xform, ok := pn.GetAttribute("XREALMITEM").(map[string]string); ok { - fmt.Println("UM") - tcErr := gno.TypeCheckMemPackage2(memPkg, gs, true, true, xform) - if tcErr != nil { - //panic(fmt.Sprintf("oops %v", tcErr)) - for _, file := range memPkg.Files { - fmt.Println("FORMATTED:", file.Name) // , file.Body) - fpath := filepath.Join(dirPath, file.Name) - err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) - if err != nil { - panic(err) - } - } - } else { - for _, file := range memPkg.Files { - fmt.Println("FORMATTED:", file.Name, file.Body) - fpath := filepath.Join(dirPath, file.Name) - err = ioutil.WriteFile(fpath, []byte(file.Body), 0644) - if err != nil { - panic(err) - } - } - // fmt.Println("NO tcErr") - } + panic(err) } } @@ -312,8 +213,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { return nil } -func lintTypeCheck(io commands.IO, dirPath string, memPkg *std.MemPackage, testStore gno.Store) (errorsFound bool, err error) { - tcErr := gno.TypeCheckMemPackageTest(memPkg, testStore) +func lintTypeCheck(io commands.IO, dir string, mpkg *std.MemPackage, testStore gno.Store) (errorsFound bool, err error) { + tcErr := gno.TypeCheckMemPackageTest(mpkg, testStore) if tcErr == nil { return false, nil } @@ -323,7 +224,7 @@ func lintTypeCheck(io commands.IO, dirPath string, memPkg *std.MemPackage, testS switch err := err.(type) { case types.Error: loc := err.Fset.Position(err.Pos).String() - loc = replaceWithDirPath(loc, memPkg.Path, dirPath) + loc = replaceWithDirPath(loc, mpkg.Path, dir) io.ErrPrintln(lintIssue{ Code: lintTypeCheckError, Msg: err.Msg, @@ -333,7 +234,7 @@ func lintTypeCheck(io commands.IO, dirPath string, memPkg *std.MemPackage, testS case scanner.ErrorList: for _, scErr := range err { loc := scErr.Pos.String() - loc = replaceWithDirPath(loc, memPkg.Path, dirPath) + loc = replaceWithDirPath(loc, mpkg.Path, dir) io.ErrPrintln(lintIssue{ Code: lintParserError, Msg: scErr.Msg, @@ -343,7 +244,7 @@ func lintTypeCheck(io commands.IO, dirPath string, memPkg *std.MemPackage, testS } case scanner.Error: loc := err.Pos.String() - loc = replaceWithDirPath(loc, memPkg.Path, dirPath) + loc = replaceWithDirPath(loc, mpkg.Path, dir) io.ErrPrintln(lintIssue{ Code: lintParserError, Msg: err.Msg, @@ -357,9 +258,9 @@ func lintTypeCheck(io commands.IO, dirPath string, memPkg *std.MemPackage, testS return true, nil } -func sourceAndTestFileset(memPkg *std.MemPackage) *gno.FileSet { +func sourceAndTestFileset(mpkg *std.MemPackage) *gno.FileSet { testfiles := &gno.FileSet{} - for _, mfile := range memPkg.Files { + for _, mfile := range mpkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // Skip non-GNO files } @@ -401,7 +302,7 @@ func guessSourcePath(pkg, source string) string { // XXX: Ideally, error handling should encapsulate location details within a dedicated error type. var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) -func catchRuntimeError(dirPath, pkgPath string, stderr goio.WriteCloser, action func()) (hasError bool) { +func catchRuntimeError(dir, pkgPath string, stderr goio.WriteCloser, action func()) (hasError bool) { defer func() { // Errors catched here mostly come from: gnovm/pkg/gnolang/preprocess.go r := recover() @@ -412,21 +313,21 @@ func catchRuntimeError(dirPath, pkgPath string, stderr goio.WriteCloser, action switch verr := r.(type) { case *gno.PreprocessError: err := verr.Unwrap() - fmt.Fprintln(stderr, issueFromError(dirPath, pkgPath, err).String()) + fmt.Fprintln(stderr, issueFromError(dir, pkgPath, err).String()) case error: errors := multierr.Errors(verr) for _, err := range errors { errList, ok := err.(scanner.ErrorList) if ok { for _, errorInList := range errList { - fmt.Fprintln(stderr, issueFromError(dirPath, pkgPath, errorInList).String()) + fmt.Fprintln(stderr, issueFromError(dir, pkgPath, errorInList).String()) } } else { - fmt.Fprintln(stderr, issueFromError(dirPath, pkgPath, err).String()) + fmt.Fprintln(stderr, issueFromError(dir, pkgPath, err).String()) } } case string: - fmt.Fprintln(stderr, issueFromError(dirPath, pkgPath, errors.New(verr)).String()) + fmt.Fprintln(stderr, issueFromError(dir, pkgPath, errors.New(verr)).String()) default: panic(r) } @@ -436,13 +337,13 @@ func catchRuntimeError(dirPath, pkgPath string, stderr goio.WriteCloser, action return } -func issueFromError(dirPath, pkgPath string, err error) lintIssue { +func issueFromError(dir, pkgPath string, err error) lintIssue { var issue lintIssue issue.Confidence = 1 issue.Code = lintGnoError parsedError := strings.TrimSpace(err.Error()) - parsedError = replaceWithDirPath(parsedError, pkgPath, dirPath) + parsedError = replaceWithDirPath(parsedError, pkgPath, dir) parsedError = strings.TrimPrefix(parsedError, pkgPath+"/") matches := reParseRecover.FindStringSubmatch(parsedError) @@ -457,9 +358,9 @@ func issueFromError(dirPath, pkgPath string, err error) lintIssue { return issue } -func replaceWithDirPath(s, pkgPath, dirPath string) string { +func replaceWithDirPath(s, pkgPath, dir string) string { if strings.HasPrefix(s, pkgPath) { - return filepath.Clean(dirPath + s[len(pkgPath):]) + return filepath.Clean(dir + s[len(pkgPath):]) } return s } diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index a4d418ca19b..ed56ce36b01 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -2,10 +2,9 @@ package gnolang import ( "bytes" - "errors" "fmt" "go/ast" - "go/format" + gofmt "go/format" "go/parser" "go/token" "go/types" @@ -15,7 +14,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" - "golang.org/x/tools/go/ast/astutil" ) // type checking (using go/types) @@ -27,25 +25,25 @@ type MemPackageGetter interface { } // TypeCheckMemPackage performs type validation and checking on the given -// mempkg. To retrieve dependencies, it uses getter. +// mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. // // If format is true, the code in msmpkg will be automatically updated with the // formatted source code. -func TypeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, format bool) error { - return typeCheckMemPackage(mempkg, getter, false, format, nil) +func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, format bool) error { + return typeCheckMemPackage(mpkg, getter, false, format) } // TypeCheckMemPackageTest performs the same type checks as [TypeCheckMemPackage], // but allows re-declarations. // // Note: like TypeCheckMemPackage, this function ignores tests and filetests. -func TypeCheckMemPackageTest(mempkg *std.MemPackage, getter MemPackageGetter) error { - return typeCheckMemPackage(mempkg, getter, true, false) +func TypeCheckMemPackageTest(mpkg *std.MemPackage, getter MemPackageGetter) error { + return typeCheckMemPackage(mpkg, getter, true, false) } -func typeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, testing, format bool) error { +func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, testing, format bool) error { var errs error imp := &gnoImporter{ getter: getter, @@ -59,7 +57,7 @@ func typeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, testin } imp.cfg.Importer = imp - _, err := imp.parseCheckMemPackage(mempkg, format, xform) + _, err := imp.parseCheckMemPackage(mpkg, format) // prefer to return errs instead of err: // err will generally contain only the first error encountered. if errs != nil { @@ -103,13 +101,13 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac g.cache[path] = gnoImporterResult{err: err} return nil, err } - fmt_ := false - result, err := g.parseCheckMemPackage(mpkg, fmt_, nil) + format := false + result, err := g.parseCheckMemPackage(mpkg, format) g.cache[path] = gnoImporterResult{pkg: result, err: err} return result, err } -func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt_ bool) (*types.Package, error) { +func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, format bool) (*types.Package, error) { // This map is used to allow for function re-definitions, which are allowed // in Gno (testing context) but not in Go. // This map links each function identifier with a closure to remove its @@ -148,9 +146,9 @@ func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt_ bool) (*ty // Enforce formatting. // This must happen before logical transforms. - if fmt_ && xform == nil { + if format { var buf bytes.Buffer - err = format.Node(&buf, fset, f) + err = gofmt.Node(&buf, fset, f) if err != nil { errs = multierr.Append(errs, err) continue @@ -164,29 +162,12 @@ func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt_ bool) (*ty // No need to filter because of gnobuiltins.go. // But keep this code block for future transforms. /* - // filter crossings for type checker - if err := filterCrossing(f); err != nil { + // transpile for Gno 0.9 + if err := transpileToGno0p9(f); err != nil { errs = multierr.Append(errs, err) continue } */ - - if xform != nil { - // transform for interrealm spec 2 - if err := transformCrossing(mpkg.Path, fset, file.Name, f, xform); err != nil { - errs = multierr.Append(errs, err) - continue - } - var buf bytes.Buffer - err = format.Node(&buf, fset, f) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - file.Body = buf.String() - // fmt.Println("FORMATTED") XXX - } - files = append(files, f) } if errs != nil { @@ -202,8 +183,7 @@ func istypednil(x any) bool { return false } // shim func crossing() { } // shim func cross[F any](fn F) F { return fn } // shim func revive[F any](fn F) any { return nil } // shim -type realm struct{} // shim -// var nilrealm realm // shim +type realm interface{} // shim `, mpkg.Name), } f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) @@ -235,87 +215,3 @@ func deleteOldIdents(idents map[string]func(), f *ast.File) { } } } - -/* -// This is how ast filtering would have worked. -// Keep this comment block around in case we need it. -func filterCrossing(f *ast.File) (err error) { - astutil.Apply(f, nil, func(c *astutil.Cursor) bool { - switch n := c.Node().(type) { - case *ast.ExprStmt: - if ce, ok := n.X.(*ast.CallExpr); ok { - if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { - // Validate syntax. - if len(ce.Args) != 0 { - err = errors.New("crossing called with non empty parameters") - } - // Delete statement 'crossing()'. - c.Delete() - } - } - case *ast.CallExpr: - if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { - // Replace expression 'cross(x)' by 'x'. - var a ast.Node - if len(n.Args) == 1 { - a = n.Args[0] - } else { - err = errors.New("cross called with invalid parameters") - } - c.Replace(a) - } - } - return true - }) - return err -} -*/ - -func transformCrossing(pkgPath string, fs *token.FileSet, fileName string, f *ast.File, xform map[string]string) (err error) { - astutil.Apply(f, nil, func(c *astutil.Cursor) bool { - switch n := c.Node().(type) { - case *ast.ExprStmt: - if ce, ok := n.X.(*ast.CallExpr); ok { - if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { - // Validate syntax. - if len(ce.Args) != 0 { - err = errors.New("crossing called with non empty parameters") - } - // Delete statement 'crossing()'. - c.Delete() - // XXX how do you remove the newline after crossing()? - } - } - case *ast.FuncDecl: - pos := n.Pos() - posn := fs.Position(pos) - l, c := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, l, c) - if xform[key] == "add curfunc" { - n.Type.Params.List = append([]*ast.Field{&ast.Field{ - Names: []*ast.Ident{ast.NewIdent("cur")}, - Type: ast.NewIdent("realm"), - }}, n.Type.Params.List...) - } - case *ast.CallExpr: - pos := n.Pos() - posn := fs.Position(pos) - l, c := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, l, c) - if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { - // Skip these. - // Gno AST doesn't store the end location, only the start. - // cross(x)(...) and cross(x) have the same start. - return true - } - //fmt.Println("AST APPLY CALLEXPR", key, n) - if xform[key] == "add curcall" { - n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) - } else if xform[key] == "add nilrealm" { - // n.Args = append([]ast.Expr{ast.NewIdent("nilrealm")}, n.Args...) - } - } - return true - }) - return err -} diff --git a/gnovm/pkg/gnolang/preprocess2.go b/gnovm/pkg/gnolang/preprocess2.go deleted file mode 100644 index 9dd15b5c918..00000000000 --- a/gnovm/pkg/gnolang/preprocess2.go +++ /dev/null @@ -1,148 +0,0 @@ -package gnolang - -import ( - "fmt" - "reflect" -) - -type XRealmItem struct { - Type string - Location -} - -// t: type, p: pkgpath, f: filename, l: line, c: column -func addXRealmItem(n Node, t string, p string, f string, l int, c int) { - x, _ := n.GetAttribute("XREALMITEM").(map[string]string) // p/f:l:c -> t - if x == nil { - x = make(map[string]string) - n.SetAttribute("XREALMITEM", x) - } - key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) - x[key] = t -} - -// Finds XRealmItems for interream spec 2 transpiling tool. -// Sets to bn attribute XREALMITEM. -func FindXRealmItems(store Store, pn *PackageNode, bn BlockNode) { - // create stack of BlockNodes. - var stack []BlockNode = make([]BlockNode, 0, 32) - var last BlockNode = pn - stack = append(stack, last) - - // Iterate over all nodes recursively. - _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { - defer doRecover(stack, n) - - if debug { - debug.Printf("FindXRealmItems %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) - } - - switch stage { - // ---------------------------------------- - case TRANS_BLOCK: - pushInitBlock(n.(BlockNode), &last, &stack) - - // ---------------------------------------- - case TRANS_LEAVE: - // Pop block from stack. - // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK - // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR - // POP BLOCK YOURSELF. - defer func() { - switch n.(type) { - case BlockNode: - stack = stack[:len(stack)-1] - last = stack[len(stack)-1] - } - }() - - switch n := n.(type) { - case *CallExpr: - if _, ok := n.Func.(*constTypeExpr); ok { - fmt.Println("CONOST1", n) - return n, TRANS_CONTINUE - } else if cx, ok := n.Func.(*ConstExpr); ok { - fmt.Println("CONOST2", n) - if cx.TypedValue.T.Kind() != FuncKind { - return n, TRANS_CONTINUE - } - fv := cx.GetFunc() - if fv.PkgPath == uversePkgPath && fv.Name == "cross" { - // XXX Add a 'nilrealm' as first argument. - // This is not part of the proposed spec, - // but Go doesn't support generic cross[T any]()T - // that curries the first `cur realm` argument. - // Gno2 can simply omit the `nilrealm` argument. - pc, ok := ns[len(ns)-1].(*CallExpr) - if !ok { - panic("cross(fn) must be followed by a call") - } - loc := last.GetLocation() - fmt.Printf("add nilrealm: %s/%s:%d:%d\n", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) - addXRealmItem(pn, "add nilrealm", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) - } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { - if !IsRealmPath(pn.PkgPath) { - panic("crossing() is only allowed in realm packages") - } - // XXX Add `cur realm` as first argument to func decl. - loc := last.GetLocation() - fmt.Printf("add curfunc: %s/%s:%d:%d\n", loc.PkgPath, loc.File, loc.Line, loc.Column) - addXRealmItem(pn, "add curfunc", loc.PkgPath, loc.File, loc.Line, loc.Column) - } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { - // reserve attach() so we can support it later. - panic("attach() not yet supported") - } - } else { - fmt.Println("CONOST3", n) - // Already handled, added "add nilrealm" - // from the "cross" case above. - if n.WithCross { - fmt.Println("CONOST4", n) - // Is a cross(fn)(...) call. - // Leave it alone. - return n, TRANS_CONTINUE - } - pv := pn.NewPackage() // temporary - store := store.BeginTransaction(nil, nil, nil) - store.SetCachePackage(pv) - m := NewMachine("x", store) - defer m.Release() - tv := TypedValue{} - func() { - // cannot be resolved statically - defer func() { - recover() - //fmt.Println("FAILED TO EVALSTATIC", n.Func, r) - }() - // try to evaluate n.Func. - tv = m.EvalStatic(last, n.Func) - }() - switch cv := tv.V.(type) { - case nil: - return n, TRANS_CONTINUE - case TypeValue: - panic("wtf") - case *FuncValue: - if cv.IsCrossing() { - // XXX Not cross-called, so add `cur` as first argument. - loc := last.GetLocation() - fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) - addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) - } - case *BoundMethodValue: - if cv.IsCrossing() { - // XXX Not cross-called, so add `cur` as first argument. - loc := last.GetLocation() - fmt.Printf("add curcall: %s/%s:%d:%d\n", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) - addXRealmItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) - } - } - } - } - // end type switch statement - // END TRANS_LEAVE ----------------------- - return n, TRANS_CONTINUE - } - return n, TRANS_CONTINUE - }) -} diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go new file mode 100644 index 00000000000..6fb41c22a7b --- /dev/null +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -0,0 +1,332 @@ +package gnolang + +import ( + "bytes" + "errors" + "fmt" + "go/ast" + gofmt "go/format" + "go/parser" + "go/token" + "path" + "reflect" + "strings" + + "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/multierr" + "golang.org/x/tools/go/ast/astutil" +) + +// Transpiles existing Gno code to Gno 0.9, the one with @cross decorators, not +// cross(fn)(...). (duh). +// +// Writes in place if dirPath is provided. +// Files without `// Gno 0.9` as the first line are considered to be for Gno +// 0.x < 0.9. +// +// xform: result of FindGno0p9XItems(). +func TranspileToGno0p9(mpkg *std.MemPackage, dirPath string, testing, format bool, xform map[string]string) error { + // This map is used to allow for function re-definitions, which are allowed + // in Gno (testing context) but not in Go. + // This map links each function identifier with a closure to remove its + // associated declaration. + var delFunc map[string]func() + if testing { + delFunc = make(map[string]func()) + } + + fset := token.NewFileSet() + files := make([]*ast.File, 0, len(mpkg.Files)) + const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution + var errs error + for _, file := range mpkg.Files { + // Ignore non-gno files. + // TODO: support filetest type checking. (should probably handle as each its + // own separate pkg, which should also be typechecked) + if !strings.HasSuffix(file.Name, ".gno") || + strings.HasSuffix(file.Name, "_test.gno") || + strings.HasSuffix(file.Name, "_filetest.gno") { + continue + } + + f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + + //---------------------------------------- + // Non-logical formatting transforms + + if delFunc != nil { + deleteOldIdents(delFunc, f) + } + + // Enforce formatting. + // This must happen before logical transforms. + if format && xform == nil { + var buf bytes.Buffer + err = gofmt.Node(&buf, fset, f) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + file.Body = buf.String() + } + + //---------------------------------------- + // Logical transforms + + if xform != nil { + // AST transform for Gno 0.9. + if err := transpileToGno0p9(mpkg.Path, fset, file.Name, f, xform); err != nil { + errs = multierr.Append(errs, err) + continue + } + // Write transformed AST to Go to file. + var buf bytes.Buffer + err = gofmt.Node(&buf, fset, f) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + file.Body = buf.String() + } + files = append(files, f) + } + if errs != nil { + return errs + } + // END processing all files. + + // Write to dirPath. + err := mpkg.WriteTo(dirPath) + return err +} + +func transpileToGno0p9(pkgPath string, fs *token.FileSet, fileName string, f *ast.File, xform map[string]string) (err error) { + + var lastLine = 0 + var didRemoveCrossing = false + var setLast = func(end token.Pos) { + posn := fs.Position(end) + lastLine = posn.Line + } + var getLine = func(pos token.Pos) int { + return fs.Position(pos).Line + } + + astutil.Apply(f, func(c *astutil.Cursor) bool { + + // Handle newlines after crossing + if didRemoveCrossing { + n := c.Node() + line := getLine(n.Pos()) + tf := fs.File(n.Pos()) + if lastLine < line { + // lastLine - 1 is the deleted crossing(). + tf.MergeLine(lastLine - 1) + // and the next empty line too. + tf.MergeLine(lastLine) + } + didRemoveCrossing = false + } + + // Main switch on c.Node() type. + switch n := c.Node().(type) { + case *ast.Ident: + if n.Name == "realm" { + // Rename name to _realm to avoid conflict with new builtin "realm". + // XXX: optimistic. + n.Name = "_realm" + } + case *ast.ExprStmt: + if ce, ok := n.X.(*ast.CallExpr); ok { + if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { + // Validate syntax. + if len(ce.Args) != 0 { + err = errors.New("crossing called with non empty parameters") + } + // Delete statement 'crossing()'. + c.Delete() + didRemoveCrossing = true + setLast(n.End()) + return false + } + } + case *ast.FuncDecl: + pos := n.Pos() + posn := fs.Position(pos) + line, col := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, line, col) + if xform[key] == "add curfunc" { + n.Type.Params.List = append([]*ast.Field{&ast.Field{ + Names: []*ast.Ident{ast.NewIdent("cur")}, + Type: ast.NewIdent("realm"), + }}, n.Type.Params.List...) + } + case *ast.CallExpr: + pos := n.Pos() + posn := fs.Position(pos) + line, col := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, line, col) + if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { + // Replace expression 'cross(x)' by 'x'. + // In Gno 0.9 @cross decorator is used instead. + var a ast.Node + if len(n.Args) == 1 { + a = n.Args[0] + } else { + err = errors.New("cross called with invalid parameters") + } + c.Replace(a) + return true + } + if xform[key] == "add curcall" { + n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) + } else if xform[key] == "add nilrealm" { + n.Args = append([]ast.Expr{ast.NewIdent("nil")}, n.Args...) + } + } + return true + }, nil) + return err +} + +//======================================== +// Find Gno0.9 XItems + +// Represents a needed transform. +type XItem struct { + Type string + Location +} + +// Finds XItems for Gno 0.9 from the Gno AST and +// stores them pn ATTR_GNO0P9_XITEMS +// Then TranspileToGno0p9() applies them to Go AST and writes them. +func FindGno0p9XItems(store Store, pn *PackageNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = pn + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("FindXItems %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_LEAVE: + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case *CallExpr: + if _, ok := n.Func.(*constTypeExpr); ok { + return n, TRANS_CONTINUE + } else if cx, ok := n.Func.(*ConstExpr); ok { + if cx.TypedValue.T.Kind() != FuncKind { + return n, TRANS_CONTINUE + } + fv := cx.GetFunc() + if fv.PkgPath == uversePkgPath && fv.Name == "cross" { + // Add a nil realm as first argument. + pc, ok := ns[len(ns)-1].(*CallExpr) + if !ok { + panic("cross(fn) must be followed by a call") + } + loc := last.GetLocation() + addXItem(pn, "add nilrealm", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { + if !IsRealmPath(pn.PkgPath) { + panic("crossing() is only allowed in realm packages") + } + // Add `cur realm` as first argument to func decl. + loc := last.GetLocation() + addXItem(pn, "add curfunc", loc.PkgPath, loc.File, loc.Line, loc.Column) + } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { + // reserve attach() so we can support it later. + panic("attach() not yet supported") + } + } else { + // Already handled, added "add nilrealm" + // from the "cross" case above. + if n.WithCross { + // Is a cross(fn)(...) call. + // Leave it alone. + return n, TRANS_CONTINUE + } + pv := pn.NewPackage() // temporary + store := store.BeginTransaction(nil, nil, nil) + store.SetCachePackage(pv) + m := NewMachine("x", store) + defer m.Release() + tv := TypedValue{} + func() { + // cannot be resolved statically + defer func() { + recover() + //fmt.Println("FAILED TO EVALSTATIC", n.Func, r) + }() + // try to evaluate n.Func. + tv = m.EvalStatic(last, n.Func) + }() + switch cv := tv.V.(type) { + case nil: + return n, TRANS_CONTINUE + case TypeValue: + panic("wtf") + case *FuncValue: + if cv.IsCrossing() { + // Not cross-called, so add `cur` as first argument. + loc := last.GetLocation() + addXItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + } + case *BoundMethodValue: + if cv.IsCrossing() { + // Not cross-called, so add `cur` as first argument. + loc := last.GetLocation() + addXItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + } + } + } + } + // end type switch statement + // END TRANS_LEAVE ----------------------- + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + +const ATTR_GNO0P9_XITEMS = "ATTR_GNO0P9_XITEMS" + +// t: type, p: pkgpath, f: filename, l: line, c: column +func addXItem(n Node, t string, p string, f string, l int, c int) { + x, _ := n.GetAttribute(ATTR_GNO0P9_XITEMS).(map[string]string) // p/f:l:c -> t + if x == nil { + x = make(map[string]string) + n.SetAttribute(ATTR_GNO0P9_XITEMS, x) + } + key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) + x[key] = t + fmt.Printf("%s:%s\n", t, key) +} diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index 7d15e6d993b..ef61ef30caa 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -59,6 +59,45 @@ var gStringerType = &DeclaredType{ sealed: true, } +var gRealmType = &DeclaredType{ + PkgPath: uversePkgPath, + Name: "realm", + Base: &InterfaceType{ + PkgPath: uversePkgPath, + Methods: []FieldType{ + { + Name: "Addr", + Type: &FuncType{ + Params: nil, + Results: []FieldType{ + { + // Name: "", + Type: StringType, // NOT std.Address. + }, + }, + }, + }, + { + Name: "Prev", + Type: &FuncType{ + Params: nil, + Results: []FieldType{ + { + // Name: "", + Type: nil, // gets filled in init() below. + }, + }, + }, + }, + }, + }, + sealed: true, +} + +func init() { + gRealmType.Base.(*InterfaceType).Methods[1].Type.(*FuncType).Results[0].Type = gRealmType +} + // ---------------------------------------- // Uverse package @@ -752,6 +791,11 @@ func makeUverseNode() { } }, ) + + //---------------------------------------- + // Gno2 types + // XXX UNCOMMENT + // def("realm", asValue(gRealmType)) defNative("crossing", nil, // params nil, // results @@ -843,6 +887,7 @@ func makeUverseNode() { // implementing istypednil() is annoying, while istypednil() shouldn't // require reflect, Gno should therefore offer istypednil() as a uverse // function. + // XXX REMOVE, move to std function. defNative("istypednil", Flds( // params "x", AnyT(), diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index a5fb811caca..b075d193030 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -2,6 +2,8 @@ package std import ( "fmt" + "io/ioutil" + "path/filepath" "regexp" "sort" "strings" @@ -24,19 +26,6 @@ type MemPackage struct { Files []*MemFile `json:"files" yaml:"files"` } -func (mempkg *MemPackage) GetFile(name string) *MemFile { - for _, memFile := range mempkg.Files { - if memFile.Name == name { - return memFile - } - } - return nil -} - -func (mempkg *MemPackage) IsEmpty() bool { - return mempkg.Name == "" || len(mempkg.Files) == 0 -} - const pathLengthLimit = 256 var ( @@ -48,36 +37,36 @@ var ( // path must not contain any dots after the first domain component. // file names must contain dots. // NOTE: this is to prevent conflicts with nested paths. -func (mempkg *MemPackage) Validate() error { +func (mpkg *MemPackage) Validate() error { // add assertion that MemPkg contains at least 1 file - if len(mempkg.Files) <= 0 { - return fmt.Errorf("no files found within package %q", mempkg.Name) + if len(mpkg.Files) <= 0 { + return fmt.Errorf("no files found within package %q", mpkg.Name) } - if len(mempkg.Path) > pathLengthLimit { - return fmt.Errorf("path length %d exceeds limit %d", len(mempkg.Path), pathLengthLimit) + if len(mpkg.Path) > pathLengthLimit { + return fmt.Errorf("path length %d exceeds limit %d", len(mpkg.Path), pathLengthLimit) } - if !rePkgName.MatchString(mempkg.Name) { - return fmt.Errorf("invalid package name %q, failed to match %q", mempkg.Name, rePkgName) + if !rePkgName.MatchString(mpkg.Name) { + return fmt.Errorf("invalid package name %q, failed to match %q", mpkg.Name, rePkgName) } - if !rePkgOrRlmPath.MatchString(mempkg.Path) { - return fmt.Errorf("invalid package/realm path %q, failed to match %q", mempkg.Path, rePkgOrRlmPath) + if !rePkgOrRlmPath.MatchString(mpkg.Path) { + return fmt.Errorf("invalid package/realm path %q, failed to match %q", mpkg.Path, rePkgOrRlmPath) } // enforce sorting files based on Go conventions for predictability sorted := sort.SliceIsSorted( - mempkg.Files, + mpkg.Files, func(i, j int) bool { - return mempkg.Files[i].Name < mempkg.Files[j].Name + return mpkg.Files[i].Name < mpkg.Files[j].Name }, ) if !sorted { - return fmt.Errorf("mempackage %q has unsorted files", mempkg.Path) + return fmt.Errorf("mempackage %q has unsorted files", mpkg.Path) } var prev string - for i, file := range mempkg.Files { + for i, file := range mpkg.Files { if !reFileName.MatchString(file.Name) { return fmt.Errorf("invalid file name %q, failed to match %q", file.Name, reFileName) } @@ -90,6 +79,31 @@ func (mempkg *MemPackage) Validate() error { return nil } +func (mpkg *MemPackage) GetFile(name string) *MemFile { + for _, memFile := range mpkg.Files { + if memFile.Name == name { + return memFile + } + } + return nil +} + +func (mpkg *MemPackage) IsEmpty() bool { + return mpkg.Name == "" || len(mpkg.Files) == 0 +} + +func (mpkg *MemPackage) WriteTo(dirPath string) error { + for _, file := range mpkg.Files { + fmt.Println("FORMATTED:", file.Name, file.Body) + fpath := filepath.Join(dirPath, file.Name) + err := ioutil.WriteFile(fpath, []byte(file.Body), 0644) + if err != nil { + return err + } + } + return nil +} + const licenseName = "LICENSE" // Splits a path into the dirpath and filename. From 32e2e78c7704bc52d83737517bbade1f242543c9 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 10 May 2025 02:35:40 -0700 Subject: [PATCH 05/83] gnomod/lint/transpile etc --- gnovm/cmd/gno/mod.go | 19 +- gnovm/cmd/gno/test.go | 15 +- gnovm/cmd/gno/tool_lint.go | 187 +++++++--- gnovm/cmd/gno/tool_transpile.go | 2 +- gnovm/pkg/doc/dirs.go | 2 +- gnovm/pkg/gnofmt/package.go | 2 +- gnovm/pkg/gnolang/gnomod.go | 78 ++++ gnovm/pkg/gnolang/go2gno.go | 65 ++-- gnovm/pkg/gnolang/gotypecheck.go | 127 ++----- gnovm/pkg/gnolang/helpers.go | 4 +- gnovm/pkg/gnolang/machine.go | 4 +- gnovm/pkg/gnolang/nodes.go | 9 +- gnovm/pkg/gnolang/preprocess.go | 15 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 499 ++++++++++++++++++-------- gnovm/pkg/gnolang/uverse.go | 3 +- gnovm/pkg/gnolang/version.go | 11 + gnovm/pkg/gnomod/file.go | 42 ++- gnovm/pkg/gnomod/gnomod.go | 4 +- gnovm/pkg/gnomod/parse.go | 87 +++-- gnovm/pkg/gnomod/parse_test.go | 10 +- gnovm/pkg/gnomod/pkg.go | 71 ---- gnovm/pkg/gnomod/pkg_test.go | 31 +- gnovm/pkg/gnomod/read.go | 3 +- gnovm/pkg/gnomod/read_test.go | 83 +++-- gnovm/pkg/gnomod/utils.go | 16 + gnovm/pkg/test/filetest.go | 13 +- gnovm/pkg/test/imports.go | 6 + tm2/pkg/std/memfile.go | 14 +- 28 files changed, 906 insertions(+), 516 deletions(-) create mode 100644 gnovm/pkg/gnolang/gnomod.go create mode 100644 gnovm/pkg/gnolang/version.go diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index d007300576e..b1747f27417 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -10,6 +10,7 @@ import ( "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload" "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher" + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/packages" "github.com/gnolang/gno/tm2/pkg/commands" @@ -179,7 +180,7 @@ func execModGraph(cfg *modGraphCfg, args []string, io commands.IO) error { stdout := io.Out() - pkgs, err := gnomod.ListPkgs(args[0]) + pkgs, err := gno.ReadPkgListFromDir(args[0]) if err != nil { return err } @@ -223,7 +224,7 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { } // parse gno.mod - gnoMod, err := gnomod.Parse(modPath, data) + gnoMod, err := gnomod.ParseBytes(modPath, data) if err != nil { return fmt.Errorf("parse: %w", err) } @@ -307,7 +308,7 @@ func execModTidy(cfg *modTidyCfg, args []string, io commands.IO) error { } if cfg.recursive { - pkgs, err := gnomod.ListPkgs(wd) + pkgs, err := gno.ReadPkgListFromDir(wd) if err != nil { return err } @@ -324,8 +325,8 @@ func execModTidy(cfg *modTidyCfg, args []string, io commands.IO) error { } func modTidyOnce(cfg *modTidyCfg, wd, pkgdir string, io commands.IO) error { - fname := filepath.Join(pkgdir, "gno.mod") - relpath, err := filepath.Rel(wd, fname) + fpath := filepath.Join(pkgdir, "gno.mod") + relpath, err := filepath.Rel(wd, fpath) if err != nil { return err } @@ -333,12 +334,12 @@ func modTidyOnce(cfg *modTidyCfg, wd, pkgdir string, io commands.IO) error { io.ErrPrintfln("%s", relpath) } - gm, err := gnomod.ParseGnoMod(fname) + gm, err := gnomod.ParseFilepath(fpath) if err != nil { return err } - gm.Write(fname) + gm.WriteFile(fpath) return nil } @@ -351,8 +352,8 @@ func execModWhy(args []string, io commands.IO) error { if err != nil { return err } - fname := filepath.Join(wd, "gno.mod") - gm, err := gnomod.ParseGnoMod(fname) + fpath := filepath.Join(wd, "gno.mod") + gm, err := gnomod.ParseFilepath(fpath) if err != nil { return err } diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 0d9a642cd53..41d1558a6f8 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -227,17 +227,19 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { io.ErrPrintfln("? %s \t[no test files]", pkg.Dir) continue } - // Determine gnoPkgPath by reading gno.mod - modfile, _ := gnomod.ParseAt(pkg.Dir) + + // Determine gnoPkgPath by reading gno.mod from disk. + // TODO: Have ReadMemPackage handle it. + modfile, _ := gnomod.ParseDir(pkg.Dir) gnoPkgPath, ok := determinePkgPath(modfile, pkg.Dir, cfg.rootDir) if !ok { io.ErrPrintfln("--- WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") } + // Read MemPackage and lint/pretranspile/format. + // (gno.mod will be read again). memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) - var hasError bool - startedAt := time.Now() runtimeError := catchRuntimeError(pkg.Dir, gnoPkgPath, io.Err(), func() { if modfile == nil || !modfile.Draft { @@ -255,9 +257,9 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { }) hasError = hasError || runtimeError + // Print status with duration. duration := time.Since(startedAt) dstr := fmtDuration(duration) - if hasError || err != nil { if err != nil { io.ErrPrintfln("%s: test pkg: %v", pkg.Dir, err) @@ -282,12 +284,11 @@ func determinePkgPath(modfile *gnomod.File, dir, rootDir string) (string, bool) if modfile != nil { return modfile.Module.Mod.Path, true } - if path := pkgPathFromRootDir(dir, rootDir); path != "" { return path, true } // unable to read pkgPath from gno.mod, use a deterministic path. - return "gno.land/r/txtar", false // XXX: gno.land hardcoded for convenience. + return "gno.land/r/test", false // XXX: gno.land hardcoded for convenience. } // attempts to determine the full gno pkg path by analyzing the directory. diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 6f75dfb04f4..67fc91c384a 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -9,8 +9,10 @@ import ( "go/types" goio "io" "os" + "path" "path/filepath" "regexp" + rdebug "runtime/debug" "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" @@ -23,16 +25,18 @@ import ( ) type processedPackage struct { - mpkg *std.MemPackage - fset *gno.FileSet - pn *gno.PackageNode + mpkg *std.MemPackage + fset *gno.FileSet + pn *gno.PackageNode + _tests []*gno.FileSet + ftests []*gno.FileSet } type lintCfg struct { verbose bool rootDir string - // min_confidence: minimum confidence of a problem to print it (default 0.8) - // auto-fix: apply suggested fixes automatically. + // min_confidence: minimum confidence of a problem to print it + // (default 0.8) auto-fix: apply suggested fixes automatically. } func newLintCmd(io commands.IO) *commands.Command { @@ -58,14 +62,14 @@ func (c *lintCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)") } -type lintCode int +type lintCode string const ( - lintUnknown lintCode = iota - lintGnoMod - lintGnoError - lintParserError - lintTypeCheckError + lintUnknown lintCode = "lintUnknown" + lintGnoMod = "lintGnoMod" + lintGnoError = "lintGnoError" + lintParserError = "lintParserError" + lintTypeCheckError = "lintTypeCheckError" // TODO: add new linter codes here. ) @@ -80,7 +84,7 @@ type lintIssue struct { func (i lintIssue) String() string { // TODO: consider crafting a doc URL based on Code. - return fmt.Sprintf("%s: %s (code=%d)", i.Location, i.Msg, i.Code) + return fmt.Sprintf("%s: %s (code=%s)", i.Location, i.Msg, i.Code) } func execLint(cfg *lintCfg, args []string, io commands.IO) error { @@ -122,44 +126,56 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { dir = filepath.Dir(dir) } - // Check if 'gno.mod' exists - gmFile, err := gnomod.ParseAt(dir) + // TODO: This should be handled by ReadMemPackage. + fname := path.Join(dir, "gno.mod") + gmf, err := gnomod.ParseFilepath(fname) if err != nil { issue := lintIssue{ Code: lintGnoMod, - Confidence: 1, - Location: dir, + Confidence: 1, // ?? + Location: fname, Msg: err.Error(), } io.ErrPrintln(issue) hasError = true + continue } - pkgPath, _ := determinePkgPath(gmFile, dir, cfg.rootDir) + // Read MemPackage with pkgPath. + pkgPath, _ := determinePkgPath(gmf, dir, cfg.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { - io.ErrPrintln(issueFromError(dir, pkgPath, err).String()) + io.ErrPrintln(issueFromError( + dir, pkgPath, err, "ReadMemPackge").String()) hasError = true continue } // Perform imports using the parent store. if err := test.LoadImports(ts, mpkg); err != nil { - io.ErrPrintln(issueFromError(dir, pkgPath, err).String()) + io.ErrPrintln(issueFromError( + dir, pkgPath, err, "LoadImports").String()) hasError = true continue } // Handle runtime errors hasRuntimeErr := catchRuntimeError(dir, pkgPath, io.Err(), func() { - // Wrap in cache wrap so execution of the linter doesn't impact - // other packages. + // Wrap in cache wrap so execution of the linter + // doesn't impact other packages. cw := bs.CacheWrap() gs := ts.BeginTransaction(cw, cw, nil) // Run type checking - if gmFile == nil || !gmFile.Draft { - foundErr, err := lintTypeCheck(io, dir, mpkg, gs) + if gmf == nil || !gmf.Draft { + // NOTE: + // lintTypeCheck() --> + // TypeCheckMemPackageTest() --> + // imp.parseCheckMemPackage() --> + // PretranspileToGno0p9() + // That is, it will pre-transpile if needed. + foundErr, err := lintTypeCheck( + io, dir, mpkg, gs) if err != nil { io.ErrPrintln(err) hasError = true @@ -170,20 +186,44 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } + // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) - defer tm.Release() // Check test files - packageFiles := sourceAndTestFileset(mpkg) - - pn, _ := tm.PreprocessFiles(mpkg.Name, mpkg.Path, packageFiles, false, false) - ppkgs[mpkg.Path] = processedPackage{mpkg, packageFiles, pn} - - // Use the preprocessor to collect the transformations needed to be done. - // They are collected in pn.GetAttribute("XREALMITEM") - for _, fn := range packageFiles.Files { - gno.FindGno0p9XItems(gs, pn, fn) + all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + + // Preprocess fset files (w/ some _test.gno). + pn, _ := tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + // Preprocess _test files (all _test.gno). + for _, fset := range _tests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + } + // Preprocess _filetest.gno files. + for _, fset := range ftests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + } + // Record results. + ppkgs[dir] = processedPackage{ + mpkg, fset, pn, _tests, ftests} + // Get the gno.mod file. + gmf, err := gnomod.ParseMemPackage(mpkg) + if err != nil { + io.ErrPrintln(err) + hasError = true + } + // Before Gno 0.9 is Gno 0.0 (no "gno 0.9" in gno.mod) + if gmf.Gno.Version == "0.0" { + // Use the preprocessor to collect the + // transformations needed to be done. + // They are collected in + // pn.GetAttribute("XREALMITEM") + for _, fn := range all.Files { + gno.FindGno0p9XItems(gs, pn, fn) + } } }) if hasRuntimeErr { @@ -199,8 +239,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { panic("where did it go") } mpkg, pn := ppkg.mpkg, ppkg.pn - xform := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) - err := gno.TranspileToGno0p9(mpkg, dir, true, true, xform) + xform, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) + err := gno.TranspileToGno0p9(mpkg, dir, xform) if err != nil { panic(err) } @@ -258,8 +298,18 @@ func lintTypeCheck(io commands.IO, dir string, mpkg *std.MemPackage, testStore g return true, nil } -func sourceAndTestFileset(mpkg *std.MemPackage) *gno.FileSet { - testfiles := &gno.FileSet{} +// Sorts mpkg files into the following filesets: +// - all: all files +// - fset: all normal and _test.go files in package excluding `package xxx_test` +// integration *_test.gno files. +// - _tests: `package xxx_test` integration *_test.gno files, each in their +// own file set. +// - ftests: *_filetest.gno file tests, each in their own file set. +func sourceAndTestFileset(mpkg *std.MemPackage) ( + all, fset *gno.FileSet, _tests, ftests []*gno.FileSet) { + + all = &gno.FileSet{} + fset = &gno.FileSet{} for _, mfile := range mpkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // Skip non-GNO files @@ -269,15 +319,24 @@ func sourceAndTestFileset(mpkg *std.MemPackage) *gno.FileSet { if n == nil { continue // Skip empty files } - - // XXX: package ending with `_test` is not supported yet - if !strings.HasSuffix(mfile.Name, "_filetest.gno") && - !strings.HasSuffix(string(n.PkgName), "_test") { - // Keep only test files - testfiles.AddFiles(n) + all.AddFiles(n) + if string(n.PkgName) == string(mpkg.Name)+"_test" { + // A xxx_file integration test is a package of its own. + fset := &gno.FileSet{} + fset.AddFiles(n) + _tests = append(_tests, fset) + } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { + // A _filetest.gno is a package of its own. + fset := &gno.FileSet{} + fset.AddFiles(n) + ftests = append(ftests, fset) + } else { + // All normal package files and, + // _test.gno files that aren't xxx_test. + fset.AddFiles(n) } } - return testfiles + return } func guessSourcePath(pkg, source string) string { @@ -298,36 +357,56 @@ func guessSourcePath(pkg, source string) string { } // reParseRecover is a regex designed to parse error details from a string. -// It extracts the file location, line number, and error message from a formatted error string. -// XXX: Ideally, error handling should encapsulate location details within a dedicated error type. +// It extracts the file location, line number, and error message from a +// formatted error string. +// XXX: Ideally, error handling should encapsulate location details within a +// dedicated error type. var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) func catchRuntimeError(dir, pkgPath string, stderr goio.WriteCloser, action func()) (hasError bool) { defer func() { - // Errors catched here mostly come from: gnovm/pkg/gnolang/preprocess.go + // Errors catched here mostly come from: + // gnovm/pkg/gnolang/preprocess.go r := recover() if r == nil { return } + rdebug.PrintStack() hasError = true switch verr := r.(type) { case *gno.PreprocessError: err := verr.Unwrap() - fmt.Fprintln(stderr, issueFromError(dir, pkgPath, err).String()) + fmt.Fprintln(stderr, issueFromError( + dir, pkgPath, err, "panic=PreprocessError").String()) case error: errors := multierr.Errors(verr) for _, err := range errors { errList, ok := err.(scanner.ErrorList) if ok { for _, errorInList := range errList { - fmt.Fprintln(stderr, issueFromError(dir, pkgPath, errorInList).String()) + fmt.Fprintln(stderr, issueFromError( + dir, + pkgPath, + errorInList, + "panic=+go/scanner.ErrorList", + ).String()) } } else { - fmt.Fprintln(stderr, issueFromError(dir, pkgPath, err).String()) + fmt.Fprintln(stderr, issueFromError( + dir, + pkgPath, + err, + "panic=error", + ).String()) } } case string: - fmt.Fprintln(stderr, issueFromError(dir, pkgPath, errors.New(verr)).String()) + fmt.Fprintln(stderr, issueFromError( + dir, + pkgPath, + errors.New(verr), + "panic=string", + ).String()) default: panic(r) } @@ -337,7 +416,7 @@ func catchRuntimeError(dir, pkgPath string, stderr goio.WriteCloser, action func return } -func issueFromError(dir, pkgPath string, err error) lintIssue { +func issueFromError(dir, pkgPath string, err error, why string) lintIssue { var issue lintIssue issue.Confidence = 1 issue.Code = lintGnoError @@ -350,10 +429,10 @@ func issueFromError(dir, pkgPath string, err error) lintIssue { if len(matches) > 0 { sourcepath := guessSourcePath(pkgPath, matches[1]) issue.Location = sourcepath + matches[2] - issue.Msg = strings.TrimSpace(matches[3]) + issue.Msg = strings.TrimSpace(matches[3]) + " (" + why + ")" } else { issue.Location = fmt.Sprintf("%s:0", filepath.Clean(pkgPath)) - issue.Msg = err.Error() + issue.Msg = err.Error() + " (" + why + ")" } return issue } diff --git a/gnovm/cmd/gno/tool_transpile.go b/gnovm/cmd/gno/tool_transpile.go index 1e3081ca2b0..bd312116417 100644 --- a/gnovm/cmd/gno/tool_transpile.go +++ b/gnovm/cmd/gno/tool_transpile.go @@ -205,7 +205,7 @@ func transpilePkg(dirPath string, opts *transpileOptions) error { } opts.markAsTranspiled(dirPath) - gmod, err := gnomod.ParseAt(dirPath) + gmod, err := gnomod.ParseDir(dirPath) if err != nil && !errors.Is(err, gnomod.ErrGnoModNotFound) { return err } diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index a5a5e882df6..86739f47769 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -56,7 +56,7 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { } for _, mdir := range modDirs { - gm, err := gnomod.ParseGnoMod(filepath.Join(mdir, "gno.mod")) + gm, err := gnomod.ParseFilepath(filepath.Join(mdir, "gno.mod")) if err != nil { log.Printf("%v", err) continue diff --git a/gnovm/pkg/gnofmt/package.go b/gnovm/pkg/gnofmt/package.go index c576bd8ee78..579e1d063ca 100644 --- a/gnovm/pkg/gnofmt/package.go +++ b/gnovm/pkg/gnofmt/package.go @@ -106,7 +106,7 @@ func ParsePackage(fset *token.FileSet, root string, dir string) (Package, error) } case err == nil: - gnoMod, err := gnomod.Parse(gnoModPath, data) + gnoMod, err := gnomod.ParseBytes(gnoModPath, data) if err != nil { return nil, fmt.Errorf("unable to parse gnomod %q: %w", gnoModPath, err) } diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go new file mode 100644 index 00000000000..f2cb3577653 --- /dev/null +++ b/gnovm/pkg/gnolang/gnomod.go @@ -0,0 +1,78 @@ +package gnolang + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/packages" + "github.com/gnolang/gno/tm2/pkg/std" +) + +// ReadPkgListFromDir() lists all gno packages in the given dir directory. +func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { + var pkgs []gnomod.Pkg + + err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + return nil + } + gmfPath := filepath.Join(path, "gno.mod") + data, err := os.ReadFile(gmfPath) + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + + gmf, err := gnomod.ParseBytes(gmfPath, data) + if err != nil { + return fmt.Errorf("parse: %w", err) + } + gmf.Sanitize() + if err := gmf.Validate(); err != nil { + return fmt.Errorf("failed to validate gno.mod in %s: %w", gmfPath, err) + } + + pkg, err := ReadMemPackage(path, gmf.Module.Mod.Path) + if err != nil { + // ignore package files on error + pkg = &std.MemPackage{} + } + + importsMap, err := packages.Imports(pkg, nil) + if err != nil { + // ignore imports on error + importsMap = nil + } + importsRaw := importsMap.Merge(packages.FileKindPackageSource, packages.FileKindTest, packages.FileKindXTest) + + imports := make([]string, 0, len(importsRaw)) + for _, imp := range importsRaw { + // remove self and standard libraries from imports + if imp.PkgPath != gmf.Module.Mod.Path && + !IsStdlib(imp.PkgPath) { + imports = append(imports, imp.PkgPath) + } + } + + pkgs = append(pkgs, gnomod.Pkg{ + Dir: path, + Name: gmf.Module.Mod.Path, + Draft: gmf.Draft, + Imports: imports, + }) + return nil + }) + if err != nil { + return nil, err + } + + return pkgs, nil +} diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index f8d7dc707c5..d43cc9df703 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -31,8 +31,10 @@ package gnolang */ import ( + "bytes" "fmt" "go/ast" + gofmt "go/format" "go/parser" "go/token" "os" @@ -105,7 +107,7 @@ func ParseFile(filename string, body string) (fn *FileNode, err error) { // TODO(morgan): would be nice to add parser.SkipObjectResolution as we don't // seem to be using its features, but this breaks when testing (specifically redeclaration tests). const parseOpts = parser.ParseComments | parser.DeclarationErrors - f, err := parser.ParseFile(fs, filename, body, parseOpts) + astf, err := parser.ParseFile(fs, filename, body, parseOpts) if err != nil { return nil, err } @@ -125,18 +127,29 @@ func ParseFile(filename string, body string) (fn *FileNode, err error) { } }() // parse with Go2Gno. - fn = Go2Gno(fs, f).(*FileNode) + fn = Go2Gno(fs, astf).(*FileNode) fn.Name = Name(filename) return fn, nil } -func setLoc(fs *token.FileSet, pos token.Pos, n Node) Node { +func setLoc(fs *token.FileSet, astn ast.Node, n Node) Node { + pos := astn.Pos() posn := fs.Position(pos) n.SetLine(posn.Line) n.SetColumn(posn.Column) return n } +func sprintASTNode(fs *token.FileSet, astn ast.Node) string { + // Write ast.Node as string. + var buf bytes.Buffer + err := gofmt.Node(&buf, fs, astn) + if err != nil { + panic(fmt.Errorf("stringifying ast.Node: %v", err)) + } + return buf.String() +} + // If gon is a *ast.File, the name must be filled later. func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { if gon == nil { @@ -145,7 +158,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { if fs != nil { defer func() { if n != nil { - setLoc(fs, gon.Pos(), n) + setLoc(fs, gon, n) } }() } @@ -316,7 +329,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { } case *ast.BlockStmt: return &BlockStmt{ - Body: toStmts(fs, gon.List), + Body: toBody(fs, gon), } case *ast.BranchStmt: return &BranchStmt{ @@ -341,13 +354,13 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { Init: toSimp(fs, gon.Init), Cond: toExpr(fs, gon.Cond), Post: toSimp(fs, gon.Post), - Body: toStmts(fs, gon.Body.List), + Body: toBody(fs, gon.Body), } case *ast.IfStmt: thenStmt := IfCaseStmt{ - Body: toStmts(fs, gon.Body.List), + Body: toBody(fs, gon.Body), } - setLoc(fs, gon.Body.Pos(), &thenStmt) + setLoc(fs, gon.Body, &thenStmt) ess := []Stmt(nil) if gon.Else != nil { if _, ok := gon.Else.(*ast.BlockStmt); ok { @@ -360,7 +373,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { Body: ess, } if gon.Else != nil { - setLoc(fs, gon.Else.Pos(), &elseStmt) + setLoc(fs, gon.Else, &elseStmt) } return &IfStmt{ Init: toSimp(fs, gon.Init), @@ -392,21 +405,23 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { case *ast.TypeSwitchStmt: switch as := gon.Assign.(type) { case *ast.AssignStmt: - return &SwitchStmt{ + stmt := &SwitchStmt{ Init: toStmt(fs, gon.Init), X: toExpr(fs, as.Rhs[0].(*ast.TypeAssertExpr).X), IsTypeSwitch: true, Clauses: toClauses(fs, gon.Body.List), VarName: toName(as.Lhs[0].(*ast.Ident)), } + return stmt case *ast.ExprStmt: - return &SwitchStmt{ + stmt := &SwitchStmt{ Init: toStmt(fs, gon.Init), X: toExpr(fs, as.X.(*ast.TypeAssertExpr).X), IsTypeSwitch: true, Clauses: toClauses(fs, gon.Body.List), VarName: "", } + return stmt default: panicWithPos("unexpected *ast.TypeSwitchStmt.Assign type %s", reflect.TypeOf(gon.Assign).String()) @@ -650,7 +665,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Type: tipe, IsAlias: alias, } - setLoc(fs, s.Pos(), td) + setLoc(fs, s, td) ds = append(ds, td) case *ast.ValueSpec: if gd.Tok == token.CONST { @@ -683,7 +698,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Const: true, } cd.SetAttribute(ATTR_IOTA, si) - setLoc(fs, s.Pos(), cd) + setLoc(fs, s, cd) ds = append(ds, cd) } else { var names []NameExpr @@ -702,7 +717,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Values: values, Const: false, } - setLoc(fs, s.Pos(), vd) + setLoc(fs, s, vd) ds = append(ds, vd) } case *ast.ImportSpec: @@ -714,7 +729,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { NameExpr: *Nx(toName(s.Name)), PkgPath: path, } - setLoc(fs, s.Pos(), im) + setLoc(fs, s, im) ds = append(ds, im) default: panic(fmt.Sprintf( @@ -752,19 +767,23 @@ func toFields(fs *token.FileSet, fields ...*ast.Field) (ftxs []FieldTypeExpr) { for _, f := range fields { if len(f.Names) == 0 { // a single unnamed field w/ type - ftxs = append(ftxs, FieldTypeExpr{ + ftx := FieldTypeExpr{ NameExpr: *Nx(""), Type: toExpr(fs, f.Type), Tag: toExpr(fs, f.Tag), - }) + } + setLoc(fs, f, &ftx) + ftxs = append(ftxs, ftx) } else { // one or more named fields for _, n := range f.Names { - ftxs = append(ftxs, FieldTypeExpr{ + ftx := FieldTypeExpr{ NameExpr: *Nx(toName(n)), Type: toExpr(fs, f.Type), Tag: toExpr(fs, f.Tag), - }) + } + setLoc(fs, f, &ftx) + ftxs = append(ftxs, ftx) } } } @@ -777,10 +796,12 @@ func toKeyValueExprs(fs *token.FileSet, elts []ast.Expr) (kvxs KeyValueExprs) { if kvx, ok := x.(*ast.KeyValueExpr); ok { kvxs[i] = *Go2Gno(fs, kvx).(*KeyValueExpr) } else { - kvxs[i] = KeyValueExpr{ + kvx := KeyValueExpr{ Key: nil, Value: toExpr(fs, x), } + setLoc(fs, x, &kvx) + kvxs[i] = kvx } } return @@ -811,8 +832,10 @@ func toClauses(fs *token.FileSet, csz []ast.Stmt) []SwitchClauseStmt { } func toSwitchClauseStmt(fs *token.FileSet, cc *ast.CaseClause) SwitchClauseStmt { - return SwitchClauseStmt{ + scs := SwitchClauseStmt{ Cases: toExprs(fs, cc.List), Body: toStmts(fs, cc.Body), } + setLoc(fs, cc, &scs) + return scs } diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index ed56ce36b01..075dd875e8c 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -1,16 +1,12 @@ package gnolang import ( - "bytes" "fmt" "go/ast" - gofmt "go/format" "go/parser" - "go/token" "go/types" "path" "slices" - "strings" "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" @@ -28,22 +24,23 @@ type MemPackageGetter interface { // mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. -// -// If format is true, the code in msmpkg will be automatically updated with the -// formatted source code. -func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, format bool) error { - return typeCheckMemPackage(mpkg, getter, false, format) +func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) error { + return typeCheckMemPackage(mpkg, getter, false) } -// TypeCheckMemPackageTest performs the same type checks as [TypeCheckMemPackage], -// but allows re-declarations. +// TypeCheckMemPackageTest performs the same type checks as +// [TypeCheckMemPackage], but allows re-declarations. // -// Note: like TypeCheckMemPackage, this function ignores tests and filetests. +// NOTE: like TypeCheckMemPackage, this function ignores tests and filetests. func TypeCheckMemPackageTest(mpkg *std.MemPackage, getter MemPackageGetter) error { - return typeCheckMemPackage(mpkg, getter, true, false) + return typeCheckMemPackage(mpkg, getter, true) } -func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, testing, format bool) error { +func typeCheckMemPackage( + mpkg *std.MemPackage, + getter MemPackageGetter, + testing bool) error { + var errs error imp := &gnoImporter{ getter: getter, @@ -57,7 +54,7 @@ func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, testing, } imp.cfg.Importer = imp - _, err := imp.parseCheckMemPackage(mpkg, format) + _, err := imp.parseCheckMemPackage(mpkg) // prefer to return errs instead of err: // err will generally contain only the first error encountered. if errs != nil { @@ -101,78 +98,19 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac g.cache[path] = gnoImporterResult{err: err} return nil, err } - format := false - result, err := g.parseCheckMemPackage(mpkg, format) + result, err := g.parseCheckMemPackage(mpkg) g.cache[path] = gnoImporterResult{pkg: result, err: err} return result, err } -func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, format bool) (*types.Package, error) { - // This map is used to allow for function re-definitions, which are allowed - // in Gno (testing context) but not in Go. - // This map links each function identifier with a closure to remove its - // associated declaration. - var delFunc map[string]func() - if g.allowRedefinitions { - delFunc = make(map[string]func()) - } +func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage) (*types.Package, error) { - fset := token.NewFileSet() - files := make([]*ast.File, 0, len(mpkg.Files)) - const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var errs error - for _, file := range mpkg.Files { - // Ignore non-gno files. - // TODO: support filetest type checking. (should probably handle as each its - // own separate pkg, which should also be typechecked) - if !strings.HasSuffix(file.Name, ".gno") || - strings.HasSuffix(file.Name, "_test.gno") || - strings.HasSuffix(file.Name, "_filetest.gno") { - continue - } - - f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - - //---------------------------------------- - // Non-logical formatting transforms - - if delFunc != nil { - deleteOldIdents(delFunc, f) - } - - // Enforce formatting. - // This must happen before logical transforms. - if format { - var buf bytes.Buffer - err = gofmt.Node(&buf, fset, f) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - file.Body = buf.String() - } - - //---------------------------------------- - // Logical transforms - - // No need to filter because of gnobuiltins.go. - // But keep this code block for future transforms. - /* - // transpile for Gno 0.9 - if err := transpileToGno0p9(f); err != nil { - errs = multierr.Append(errs, err) - continue - } - */ - files = append(files, f) - } - if errs != nil { - return nil, errs + /* NOTE: Don't pre-transpile here; `gno lint` and fix the source first. + fset, astfs, err := PretranspileToGno0p9(mpkg, false) + if err != nil { + return nil, err } + */ // Add builtins file. file := &std.MemFile{ @@ -186,13 +124,20 @@ func revive[F any](fn F) any { return nil } // shim type realm interface{} // shim `, mpkg.Name), } - f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) + const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution + astf, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) if err != nil { panic("error parsing gotypecheck gnobuiltins.go file") } - files = append(files, f) - - pkg, err := g.cfg.Check(mpkg.Path, fset, files, nil) + astfs = append(astfs, astf) + + // Type-check pre-transpiled Gno0.9 AST in Go. + // We don't (post)-transpile because the linter + // is supposed to be used to write to the files. + // (No need to support JIT transpiling for imports) + // + // XXX The pre pre thing for @cross. + pkg, err := g.cfg.Check(mpkg.Path, fset, astfs, nil) return pkg, err } @@ -201,7 +146,9 @@ func deleteOldIdents(idents map[string]func(), f *ast.File) { fd, ok := decl.(*ast.FuncDecl) // ignore methods and init functions //nolint:goconst - if !ok || fd.Recv != nil || fd.Name.Name == "init" { + if !ok || + fd.Recv != nil || + fd.Name.Name == "init" { continue } if del := idents[fd.Name.Name]; del != nil { @@ -209,9 +156,11 @@ func deleteOldIdents(idents map[string]func(), f *ast.File) { } decl := decl idents[fd.Name.Name] = func() { - // NOTE: cannot use the index as a file may contain multiple decls to be removed, - // so removing one would make all "later" indexes wrong. - f.Decls = slices.DeleteFunc(f.Decls, func(d ast.Decl) bool { return decl == d }) + // NOTE: cannot use the index as a file may contain + // multiple decls to be removed, so removing one would + // make all "later" indexes wrong. + f.Decls = slices.DeleteFunc(f.Decls, + func(d ast.Decl) bool { return decl == d }) } } } diff --git a/gnovm/pkg/gnolang/helpers.go b/gnovm/pkg/gnolang/helpers.go index 15b484cff55..122e8d052d2 100644 --- a/gnovm/pkg/gnolang/helpers.go +++ b/gnovm/pkg/gnolang/helpers.go @@ -72,7 +72,9 @@ func IsPPackagePath(pkgPath string) bool { return true } -// IsStdlib determines whether s is a pkgpath for a standard library. +// IsStdlib determines whether s is a pkgpath for a standard library. If it +// doesn't start with a domain (e.g. has a dot), it is stdlib. This +// implementation ignores dots after the first slash. func IsStdlib(s string) bool { idx := strings.IndexByte(s, '/') if idx < 0 { diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 12583261a07..daa36ada98c 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -458,7 +458,9 @@ func (m *Machine) RunFiles(fns ...*FileNode) { } // PreprocessFiles runs Preprocess on the given files. It is used to detect -// compile-time errors in the package. +// compile-time errors in the package. It is also usde to preprocess files from +// the package getter for tests, e.g. from "gnovm/tests/files/extern/*", or from +// "examples/*". func (m *Machine) PreprocessFiles(pkgName, pkgPath string, fset *FileSet, save, withOverrides bool) (*PackageNode, *PackageValue) { if !withOverrides { if err := checkDuplicates(fset); err != nil { diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index fb2c79826a7..9fcca726b22 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1209,6 +1209,7 @@ func ReadMemPackage(dir string, pkgPath string) (*std.MemPackage, error) { allowedFiles := []string{ // make case insensitive? "LICENSE", "README.md", + "gno.mod", } allowedFileExtensions := []string{ ".gno", @@ -1258,6 +1259,9 @@ func MustReadMemPackage(dir string, pkgPath string) *std.MemPackage { // // NOTE: errors out if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). +// +// XXX TODO pkgPath should instead be derived by inspecting the contents, among them +// the gno.mod fule. func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, error) { memPkg := &std.MemPackage{Path: pkgPath} var pkgName Name @@ -1315,8 +1319,9 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { var errs error for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") || - endsWithAny(mfile.Name, []string{"_test.gno", "_filetest.gno"}) { - continue // skip spurious or test file. + endsWithAny(mfile.Name, []string{"_test.gno", "_filetest.gno"}) || + mfile.Name == "gno.mod" { + continue // skip spurious or test or gno.mod file. } n, err := ParseFile(mfile.Name, mfile.Body) if err != nil { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 20317ad5267..7c9455d75e2 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -5391,18 +5391,21 @@ func isLocallyDefined2(bn BlockNode, n Name) bool { func setNodeLines(n Node) { lastLine := 0 + lastColumn := 0 Transcribe(n, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { if stage != TRANS_ENTER { return n, TRANS_CONTINUE } - line := n.GetLine() - if line == lastLine { - } else if line == 0 { - line = lastLine - } else { - lastLine = line + line, column := n.GetLine(), n.GetColumn() + if line == 0 { + line, column = lastLine, lastColumn + } else if line != lastLine { + lastLine, lastColumn = line, column + } else if column != lastColumn { + /*lastLine,*/ lastColumn = /*line,*/ column } n.SetLine(line) + n.SetColumn(column) return n, TRANS_CONTINUE }) } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 6fb41c22a7b..4cd6d1678e0 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -12,181 +12,156 @@ import ( "reflect" "strings" - "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" "golang.org/x/tools/go/ast/astutil" + + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/tm2/pkg/std" ) -// Transpiles existing Gno code to Gno 0.9, the one with @cross decorators, not -// cross(fn)(...). (duh). +/* +The stages of Gno 0.0 --> Gno 0.9 transpiling. + + - ParseGnoMod: parse gno.mod (if any) and compare versions. + - GoParse: parse Gno to Go AST with go/parser. + - Prepare: minimal Go AST mutations for Gno VM compat. + - Find xitems: Gno AST static analaysis to produce xitems. + - Rekey xitems: re-key xitems by Go Node before line changes. + - Transpile: main Go AST mutations for Gno upgrade. +*/ + +// ======================================== +// Parses the appropriate gno.mod file from mpkg or +// generates a default one. // -// Writes in place if dirPath is provided. -// Files without `// Gno 0.9` as the first line are considered to be for Gno -// 0.x < 0.9. +// Args: +// - testing: if running tests +// - linting: if running `gno lint` transpiling. // -// xform: result of FindGno0p9XItems(). -func TranspileToGno0p9(mpkg *std.MemPackage, dirPath string, testing, format bool, xform map[string]string) error { - // This map is used to allow for function re-definitions, which are allowed - // in Gno (testing context) but not in Go. - // This map links each function identifier with a closure to remove its - // associated declaration. - var delFunc map[string]func() +// Results: +// - mod: the gno.mod file. +// - outdated: true if it should be transpiled to the current version. +func ParseGnoMod(mpkg *MemPackage, testing, linting bool) ( + mod *gnomod.File, outdated bool) { + if testing { - delFunc = make(map[string]func()) + // If we are testing we assume files already conform to the + // latest version. If they don't, run `gno lint` first before + // running tests. + mod, _ = gnomod.ParseBytes(gnomodTesting) + } else if IsStdlib(mpkg.Path) { + // stdlib/extern packages are assumed up to date. + mod, _ = gnomod.ParseBytes(gnomodTesting) + } else if mod, _ = gnomod.ParseMemPackage(mpkg); mod == nil { + // gno.mod doesn't exist. + mod, _ = gnomod.ParseBytes(gnomodDefault) + outdated = true + } else if mod.Gno == nil { + // 'gno 0.9' was never specified, continue + outdated = true + } else if mod.Gno.Version == GnoVersion { + // current version, nothing to do. + } else { + panic("unsupported gno version " + mod.Gno.Version) } + return +} - fset := token.NewFileSet() - files := make([]*ast.File, 0, len(mpkg.Files)) - const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var errs error +// ======================================== +// Go parse the Gno source in mpkg to Go's *token.FileSet and +// []ast.File with `go/parser`. +// +// Args: +// - withTests: if true also parses and includes all *_test.gno +// and *_filetest.gno files. +func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( + fset *token.FileSet, astfs []*ast.File, err error) { + fset = token.NewFileSet() + + // This map is used to allow for function re-definitions, which are + // allowed in Gno (testing context) but not in Go. This map links + // each function identifier with a closure to remove its associated + // declaration. + var delFunc = make(map[string]func()) + + // Go parse and collect files from mpkg. for _, file := range mpkg.Files { // Ignore non-gno files. - // TODO: support filetest type checking. (should probably handle as each its - // own separate pkg, which should also be typechecked) - if !strings.HasSuffix(file.Name, ".gno") || - strings.HasSuffix(file.Name, "_test.gno") || - strings.HasSuffix(file.Name, "_filetest.gno") { + if !strings.HasSuffix(file.Name, ".gno") { continue } - - f, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) + // Ignore _test/_filetest.gno files unless withTests. + if !withTests && + (false || + strings.HasSuffix(file.Name, "_test.gno") || + strings.HasSuffix(file.Name, "_filetest.gno")) { + continue + } + // Go parse file. + const parseOpts = parser.ParseComments | + parser.DeclarationErrors | + parser.SkipObjectResolution + var astf, err = parser.ParseFile( + fset, path.Join(mpkg.Path, file.Name), + file.Body, + parseOpts) if err != nil { errs = multierr.Append(errs, err) continue } + deleteOldIdents(delFunc, astf) + // The *ast.File passed all filters. + astfs = append(astfs, astf) + } + // END processing all files. + return fset, astfs, nil +} - //---------------------------------------- - // Non-logical formatting transforms - - if delFunc != nil { - deleteOldIdents(delFunc, f) - } - - // Enforce formatting. - // This must happen before logical transforms. - if format && xform == nil { - var buf bytes.Buffer - err = gofmt.Node(&buf, fset, f) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - file.Body = buf.String() +// ======================================== +// Prepare Gno 0.0 for Gno 0.9. +// +// When Gno syntax breaks in higher versions, existing code must first be +// pre-transcribed such that the Gno preprocessor won't panic. This allows +// old Gno code to be preprocessed and used by the Gno VM for static analysis. +// More transpiling will happen later after the preprocessed Gno AST is +// scanned for mutations on the Go AST which follows. +// +// - renames 'realm' to 'realm_' to avoid conflict with new uverse type. +// +// Any changes are applied directly on the mem package. +// Errors are returned in aggregate as a multierr type. +func PrepareGno0p9(mpkg *std.MemPackage) (errs error) { + for _, file := range mpkg.Files { + // AST transform for Gno 0.9. + err := pretranspileToGno0p9( + mpkg.Path, fset, file.Name, astf) + if err != nil { + errs = multierr.Append(errs, err) + continue } - - //---------------------------------------- - // Logical transforms - - if xform != nil { - // AST transform for Gno 0.9. - if err := transpileToGno0p9(mpkg.Path, fset, file.Name, f, xform); err != nil { - errs = multierr.Append(errs, err) - continue - } - // Write transformed AST to Go to file. - var buf bytes.Buffer - err = gofmt.Node(&buf, fset, f) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - file.Body = buf.String() + // Write formatted AST to mem file. + var buf bytes.Buffer + err = gofmt.Node(&buf, fset, astf) + if err != nil { + errs = multierr.Append(errs, err) + continue } - files = append(files, f) + file.Body = buf.String() } - if errs != nil { - return errs - } - // END processing all files. - - // Write to dirPath. - err := mpkg.WriteTo(dirPath) - return err + return } -func transpileToGno0p9(pkgPath string, fs *token.FileSet, fileName string, f *ast.File, xform map[string]string) (err error) { - - var lastLine = 0 - var didRemoveCrossing = false - var setLast = func(end token.Pos) { - posn := fs.Position(end) - lastLine = posn.Line - } - var getLine = func(pos token.Pos) int { - return fs.Position(pos).Line - } +// Pre-transpile AST mutation(s) for Gno 0.9. +func pretranspileGno0p9(f *ast.File) (err error) { + // Rename name to _realm to avoid conflict with new builtin "realm". astutil.Apply(f, func(c *astutil.Cursor) bool { - - // Handle newlines after crossing - if didRemoveCrossing { - n := c.Node() - line := getLine(n.Pos()) - tf := fs.File(n.Pos()) - if lastLine < line { - // lastLine - 1 is the deleted crossing(). - tf.MergeLine(lastLine - 1) - // and the next empty line too. - tf.MergeLine(lastLine) - } - didRemoveCrossing = false - } - - // Main switch on c.Node() type. switch n := c.Node().(type) { case *ast.Ident: if n.Name == "realm" { - // Rename name to _realm to avoid conflict with new builtin "realm". // XXX: optimistic. n.Name = "_realm" } - case *ast.ExprStmt: - if ce, ok := n.X.(*ast.CallExpr); ok { - if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { - // Validate syntax. - if len(ce.Args) != 0 { - err = errors.New("crossing called with non empty parameters") - } - // Delete statement 'crossing()'. - c.Delete() - didRemoveCrossing = true - setLast(n.End()) - return false - } - } - case *ast.FuncDecl: - pos := n.Pos() - posn := fs.Position(pos) - line, col := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, line, col) - if xform[key] == "add curfunc" { - n.Type.Params.List = append([]*ast.Field{&ast.Field{ - Names: []*ast.Ident{ast.NewIdent("cur")}, - Type: ast.NewIdent("realm"), - }}, n.Type.Params.List...) - } - case *ast.CallExpr: - pos := n.Pos() - posn := fs.Position(pos) - line, col := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fileName, line, col) - if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { - // Replace expression 'cross(x)' by 'x'. - // In Gno 0.9 @cross decorator is used instead. - var a ast.Node - if len(n.Args) == 1 { - a = n.Args[0] - } else { - err = errors.New("cross called with invalid parameters") - } - c.Replace(a) - return true - } - if xform[key] == "add curcall" { - n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) - } else if xform[key] == "add nilrealm" { - n.Args = append([]ast.Expr{ast.NewIdent("nil")}, n.Args...) - } } return true }, nil) @@ -194,18 +169,17 @@ func transpileToGno0p9(pkgPath string, fs *token.FileSet, fileName string, f *as } //======================================== -// Find Gno0.9 XItems +// Find XItems for Gno 0.0 --> Gno 0.9. -// Represents a needed transform. +// XItem represents a single needed transform. type XItem struct { Type string Location } -// Finds XItems for Gno 0.9 from the Gno AST and -// stores them pn ATTR_GNO0P9_XITEMS -// Then TranspileToGno0p9() applies them to Go AST and writes them. -func FindGno0p9XItems(store Store, pn *PackageNode, bn BlockNode) { +// Finds XItems for Gno 0.9 from the Gno AST and stores them pn +// ATTR_GNO0P9_XITEMS. +func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { // create stack of BlockNodes. var stack []BlockNode = make([]BlockNode, 0, 32) var last BlockNode = pn @@ -328,5 +302,228 @@ func addXItem(n Node, t string, p string, f string, l int, c int) { } key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) x[key] = t - fmt.Printf("%s:%s\n", t, key) + fmt.Printf("Gno 0.9 xpile +%s:%s\n", t, key) +} + +// ======================================== +// Transpiles existing Gno code to Gno 0.9, the one with @cross decorators, +// not cross(fn)(...). +// +// Writes in place if dir is provided. Transpiled packages will have their +// gno.mod Gno version to 0.9. +// +// Args: +// - dir: where to write to. +// - xform: result of FindGno0p9XItems(). +func TranspileToGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) error { + + // Return if gno.mod is current. + var mod *gnomod.File + var outdated bool = false + mod, outdated = parseGnoModFile(mpkg, false, true) + if !outdated { + return nil // already up-to-date. + } + + // Go parse and collect files from mpkg. + fset := token.NewFileSet() + var errs error + for _, file := range mpkg.Files { + // Ignore non-gno files. + if !strings.HasSuffix(file.Name, ".gno") { + continue + } + /* + // Ignore _test/_filetest.gno files unless testing. + if !testing { + if strings.HasSuffix(file.Name, "_test.gno") || + strings.HasSuffix(file.Name, "_filetest.gno") { + continue + } + } + */ + // Go parse file. + const parseOpts = parser.ParseComments | + parser.DeclarationErrors | + parser.SkipObjectResolution + var astf, err = parser.ParseFile( + fset, + path.Join(mpkg.Path, file.Name), + file.Body, + parseOpts) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + deleteOldIdents(delFunc, astf) + // AST transform for Gno 0.9 (step 1) + xform2, err := transpileToGno0p9_step1(mpkg.Path, fset, file.Name, astf, xform) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + // AST transform for Gno 0.9 (step 2) + if err := transpileToGno0p9_step2(mpkg.Path, fset, file.Name, astf, xform2); err != nil { + errs = multierr.Append(errs, err) + continue + } + // Write transformed AST to Go to file. + var buf bytes.Buffer + err = gofmt.Node(&buf, fset, astf) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + file.Body = buf.String() + } + if errs != nil { + return errs + } + // END processing all files. + + // Write version to mod and to mpkg/gno.mod. + mod.SetGno(GnoVersion) + mf := mpkg.GetFile("gno.mod") + mf.Body = mod.WriteString() + + // Write mpkg/* to dir. + err := mpkg.WriteTo(dir) + return err +} + +// We can't just apply as we encounter matches in xform unfortunately because +// it causes the lines to shift. So we first convert xform into a map keyed +// by node and then do the actual transpiling in step 2. +func transpileToGno0p9_step1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[string]string) (xform2 map[ast.Node]string, err error) { + xform2 = make(map[ast.Node]string, len(xform)) + + astutil.Apply(f, func(c *astutil.Cursor) bool { + + // Main switch on c.Node() type. + switch n := c.Node().(type) { + case *ast.FuncLit: + pos := n.Pos() + posn := fs.Position(pos) + line, col := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) + if xform != nil && xform[key] == "add curfunc" { + xform2[n] = "add curfunc" + } + case *ast.FuncDecl: + pos := n.Pos() + posn := fs.Position(pos) + line, col := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) + if xform != nil && xform[key] == "add curfunc" { + xform2[n] = "add curfunc" + } + case *ast.CallExpr: + pos := n.Pos() + posn := fs.Position(pos) + line, col := posn.Line, posn.Column + key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) + if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { + return true // can be superimposed with parent call. + } + if xform != nil && xform[key] == "add curcall" { + xform2[n] = "add curcall" + } else if xform != nil && xform[key] == "add nilrealm" { + xform2[n] = "add nilrealm" + } + } + return true + }, nil) + return xform2, err +} + +func transpileToGno0p9_step2(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[ast.Node]string) (err error) { + + var lastLine = 0 + var didRemoveCrossing = false + var setLast = func(end token.Pos) { + posn := fs.Position(end) + lastLine = posn.Line + } + var getLine = func(pos token.Pos) int { + return fs.Position(pos).Line + } + + astutil.Apply(f, func(c *astutil.Cursor) bool { + + // Handle newlines after crossing + if didRemoveCrossing { + n := c.Node() + line := getLine(n.Pos()) + tf := fs.File(n.Pos()) + if lastLine < line { + // lastLine - 1 is the deleted crossing(). + tf.MergeLine(lastLine - 1) + // and the next empty line too. + tf.MergeLine(lastLine) + } + didRemoveCrossing = false + } + + // Main switch on c.Node() type. + switch n := c.Node().(type) { + case *ast.Ident: + if n.Name == "realm_XXX_TRANSPILE" { + // Impostor varname 'realm' will become + // renamed, so reclaim 'realm'. + n.Name = "realm" + } else if n.Name == "realm" { + // Rename name to _realm to avoid conflict with new builtin "realm". + // XXX: optimistic. + n.Name = "_realm" + } + case *ast.ExprStmt: + if ce, ok := n.X.(*ast.CallExpr); ok { + if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { + // Validate syntax. + if len(ce.Args) != 0 { + err = errors.New("crossing called with non empty parameters") + } + // Delete statement 'crossing()'. + c.Delete() + didRemoveCrossing = true + setLast(n.End()) + return false + } + } + case *ast.FuncLit: + if xform != nil && xform[n] == "add curfunc" { + n.Type.Params.List = append([]*ast.Field{&ast.Field{ + Names: []*ast.Ident{ast.NewIdent("cur")}, + Type: ast.NewIdent("realm_XXX_TRANSPILE"), + }}, n.Type.Params.List...) + } + case *ast.FuncDecl: + if xform != nil && xform[n] == "add curfunc" { + n.Type.Params.List = append([]*ast.Field{&ast.Field{ + Names: []*ast.Ident{ast.NewIdent("cur")}, + Type: ast.NewIdent("realm_XXX_TRANSPILE"), + }}, n.Type.Params.List...) + } + case *ast.CallExpr: + if xform != nil && xform[n] == "add curcall" { + n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) + } else if xform != nil && xform[n] == "add nilrealm" { + n.Args = append([]ast.Expr{ast.NewIdent("nil")}, n.Args...) + } + if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { + // Replace expression 'cross(x)' by 'x'. + // In Gno 0.9 @cross decorator is used instead. + var a ast.Node + if len(n.Args) == 1 { + a = n.Args[0] + } else { + err = errors.New("cross called with invalid parameters") + } + c.Replace(a) + return true + } + } + return true + }, nil) + return err } diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index ef61ef30caa..ef1c2b46301 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -794,8 +794,7 @@ func makeUverseNode() { //---------------------------------------- // Gno2 types - // XXX UNCOMMENT - // def("realm", asValue(gRealmType)) + def("realm", asValue(gRealmType)) defNative("crossing", nil, // params nil, // results diff --git a/gnovm/pkg/gnolang/version.go b/gnovm/pkg/gnolang/version.go new file mode 100644 index 00000000000..85af860e7d5 --- /dev/null +++ b/gnovm/pkg/gnolang/version.go @@ -0,0 +1,11 @@ +package gnolang + +const ( + GnoVersion = "0.9" // Gno 0.9 is the current version. +) + +const ( + // gno.mod files assumed in testing/default contexts. + gnomodTesting = `go 0.9` // when gno.mod is missing while testing. + gnomodDefault = `go 0.0` // when gno.mod is missing in general. +) diff --git a/gnovm/pkg/gnomod/file.go b/gnovm/pkg/gnomod/file.go index a1c77b51e45..144afbd8014 100644 --- a/gnovm/pkg/gnomod/file.go +++ b/gnovm/pkg/gnomod/file.go @@ -22,13 +22,28 @@ import ( type File struct { Draft bool Module *modfile.Module - Go *modfile.Go + Gno *modfile.Go Replace []*modfile.Replace Syntax *modfile.FileSyntax } -func (f *File) AddModuleStmt(path string) error { +func (f *File) SetGno(version string) { + if f.Syntax == nil { + f.Syntax = new(modfile.FileSyntax) + } + if f.Gno == nil { + f.Gno = &modfile.Go{ + Version: version, + Syntax: addLine(f.Syntax, nil, "gno", version), + } + } else { + f.Gno.Version = version + updateLine(f.Gno.Syntax, "gno", version) + } +} + +func (f *File) SetModule(path string) { if f.Syntax == nil { f.Syntax = new(modfile.FileSyntax) } @@ -41,10 +56,9 @@ func (f *File) AddModuleStmt(path string) error { f.Module.Mod.Path = path updateLine(f.Module.Syntax, "module", modfile.AutoQuote(path)) } - return nil } -func (f *File) AddComment(text string) { +func (f *File) SetComment(text string) { if f.Syntax == nil { f.Syntax = new(modfile.FileSyntax) } @@ -59,18 +73,17 @@ func (f *File) AddComment(text string) { }) } -func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { - return addReplace(f.Syntax, &f.Replace, oldPath, oldVers, newPath, newVers) +func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) { + addReplace(f.Syntax, &f.Replace, oldPath, oldVers, newPath, newVers) } -func (f *File) DropReplace(oldPath, oldVers string) error { +func (f *File) DropReplace(oldPath, oldVers string) { for _, r := range f.Replace { if r.Old.Path == oldPath && r.Old.Version == oldVers { markLineAsRemoved(r.Syntax) *r = modfile.Replace{} } } - return nil } // Validate validates gno.mod @@ -96,16 +109,23 @@ func (f *File) Resolve(m module.Version) module.Version { } // writes file to the given absolute file path -func (f *File) Write(fname string) error { +func (f *File) WriteFile(fpath string) error { f.Syntax.Cleanup() data := modfile.Format(f.Syntax) - err := os.WriteFile(fname, data, 0o644) + err := os.WriteFile(fpath, data, 0o644) if err != nil { - return fmt.Errorf("writefile %q: %w", fname, err) + return fmt.Errorf("writefile %q: %w", fpath, err) } return nil } +// writes to a string +func (f *File) WriteString() string { + f.Syntax.Cleanup() + data := modfile.Format(f.Syntax) + return string(data) +} + func (f *File) Sanitize() { removeDups(f.Syntax, &f.Replace) } diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 3d2adc2a1aa..4ea285e34f6 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -40,8 +40,8 @@ func CreateGnoModFile(rootDir, modPath string) error { } modfile := new(File) - modfile.AddModuleStmt(modPath) - modfile.Write(filepath.Join(rootDir, "gno.mod")) + modfile.SetModule(modPath) + modfile.WriteFile(filepath.Join(rootDir, "gno.mod")) return nil } diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index edee8d2d3b5..0b68a4f5a70 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -5,15 +5,17 @@ import ( "os" "path/filepath" "reflect" + "regexp" "strings" + "github.com/gnolang/gno/tm2/pkg/std" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) -// ParseAt parses, validates and returns a gno.mod file located at dir or at +// ParseDir parses, validates and returns a gno.mod file located at dir or at // dir's parents. -func ParseAt(dir string) (*File, error) { +func ParseDir(dir string) (*File, error) { ferr := func(err error) (*File, error) { return nil, fmt.Errorf("parsing gno.mod at %s: %w", dir, err) } @@ -27,12 +29,12 @@ func ParseAt(dir string) (*File, error) { if err != nil { return ferr(err) } - fname := filepath.Join(rd, "gno.mod") - b, err := os.ReadFile(fname) + fpath := filepath.Join(rd, "gno.mod") + b, err := os.ReadFile(fpath) if err != nil { return ferr(err) } - gm, err := Parse(fname, b) + gm, err := ParseBytes(fpath, b) if err != nil { return ferr(err) } @@ -42,40 +44,36 @@ func ParseAt(dir string) (*File, error) { return gm, nil } -// tries to parse gno mod file given the filename, using Parse and Validate from -// the gnomod package -// -// TODO(tb): replace by `gnomod.ParseAt` ? The key difference is the latter -// looks for gno.mod in parent directories, while this function doesn't. -func ParseGnoMod(fname string) (*File, error) { - file, err := os.Stat(fname) +// tries to parse gno mod file given the file path, using ParseBytes and Validate. +func ParseFilepath(fpath string) (*File, error) { + file, err := os.Stat(fpath) if err != nil { return nil, fmt.Errorf("could not read gno.mod file: %w", err) } if file.IsDir() { - return nil, fmt.Errorf("invalid gno.mod at %q: is a directory", fname) + return nil, fmt.Errorf("invalid gno.mod at %q: is a directory", fpath) } - b, err := os.ReadFile(fname) + b, err := os.ReadFile(fpath) if err != nil { return nil, fmt.Errorf("could not read gno.mod file: %w", err) } - gm, err := Parse(fname, b) + gm, err := ParseBytes(fpath, b) if err != nil { - return nil, fmt.Errorf("error parsing gno.mod file at %q: %w", fname, err) + return nil, fmt.Errorf("error parsing gno.mod file at %q: %w", fpath, err) } if err := gm.Validate(); err != nil { - return nil, fmt.Errorf("error validating gno.mod file at %q: %w", fname, err) + return nil, fmt.Errorf("error validating gno.mod file at %q: %w", fpath, err) } return gm, nil } -// Parse parses and returns a gno.mod file. +// ParseBytes parses and returns a gno.mod file. // -// - file is the name of the file, used in positions and errors. +// - fname is the name of the file, used in positions and errors. // - data is the content of the file. -func Parse(file string, data []byte) (*File, error) { - fs, err := parse(file, data) +func ParseBytes(fname string, data []byte) (*File, error) { + fs, err := parse(fname, data) if err != nil { return nil, err } @@ -91,7 +89,7 @@ func Parse(file string, data []byte) (*File, error) { case *modfile.LineBlock: if len(x.Token) > 1 { errs = append(errs, modfile.Error{ - Filename: file, + Filename: fname, Pos: x.Start, Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), }) @@ -100,7 +98,7 @@ func Parse(file string, data []byte) (*File, error) { switch x.Token[0] { default: errs = append(errs, modfile.Error{ - Filename: file, + Filename: fname, Pos: x.Start, Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), }) @@ -123,6 +121,33 @@ func Parse(file string, data []byte) (*File, error) { return f, nil } +// Parse gno.mod from MemPackage, or return nil and error. +func ParseMemPackage(mpkg *std.MemPackage) (*File, error) { + mf := mpkg.GetFile("gno.mod") + if mf == nil { + return nil, fmt.Errorf( + "gno.mod not in mem package %s (name=%s)", + mpkg.Path, mpkg.Name, + ) + } + gmf, err := ParseBytes(mf.Name, []byte(mf.Body)) + if err != nil { + return nil, err + } + return gmf, nil +} + +// Must parse gno.mod from MemPackage. +func MustParseMemPackage(mpkg *std.MemPackage) *File { + gmf, err := ParseMemPackage(mpkg) + if err != nil { + panic(err) + } + return gmf +} + +var reGnoVersion = regexp.MustCompile(`^([0-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`) + func (f *File) add(errs *modfile.ErrorList, block *modfile.LineBlock, line *modfile.Line, verb string, args []string) { wrapError := func(err error) { *errs = append(*errs, modfile.Error{ @@ -139,25 +164,25 @@ func (f *File) add(errs *modfile.ErrorList, block *modfile.LineBlock, line *modf default: errorf("unknown directive: %s", verb) - case "go": - if f.Go != nil { - errorf("repeated go statement") + case "gno": + if f.Gno != nil { + errorf("repeated gno statement") return } if len(args) != 1 { - errorf("go directive expects exactly one argument") + errorf("gno directive expects exactly one argument") return - } else if !modfile.GoVersionRE.MatchString(args[0]) { + } else if !reGnoVersion.MatchString(args[0]) { fixed := false if !fixed { - errorf("invalid go version '%s': must match format 1.23", args[0]) + errorf("invalid gno version %s: must match format 1.23", args[0]) return } } line := reflect.ValueOf(line).Interface().(*modfile.Line) - f.Go = &modfile.Go{Syntax: line} - f.Go.Version = args[0] + f.Gno = &modfile.Go{Syntax: line} + f.Gno.Version = args[0] case "module": if f.Module != nil { diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index ff3de63e1bd..2f44d5830cd 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -113,7 +113,7 @@ func TestModuleDeprecated(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - f, err := Parse("in", []byte(tc.in)) + f, err := ParseBytes("in", []byte(tc.in)) assert.Nil(t, err) assert.Equal(t, tc.expected, f.Module.Deprecated) }) @@ -164,14 +164,14 @@ func TestParseDraft(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - f, err := Parse("in", []byte(tc.in)) + f, err := ParseBytes("in", []byte(tc.in)) assert.Nil(t, err) assert.Equal(t, tc.expected, f.Draft) }) } } -func TestParseGnoMod(t *testing.T) { +func TestParseFilepath(t *testing.T) { pkgDir := "bar" for _, tc := range []struct { desc, modData, modPath, errShouldContain string @@ -228,7 +228,7 @@ func TestParseGnoMod(t *testing.T) { // Create gno package createGnoModPkg(t, tempDir, pkgDir, tc.modData) - _, err := ParseGnoMod(filepath.Join(tempDir, tc.modPath)) + _, err := ParseFilepath(filepath.Join(tempDir, tc.modPath)) if tc.errShouldContain != "" { assert.ErrorContains(t, err, tc.errShouldContain) } else { @@ -270,7 +270,7 @@ func TestParseWithInvalidModulePath(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := Parse("gno.mod", []byte(tt.modData)) + _, err := ParseBytes("gno.mod", []byte(tt.modData)) if tt.errMsg != "" { assert.Error(t, err) assert.Contains(t, err.Error(), tt.errMsg) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 87233190338..af776c98c23 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -2,14 +2,9 @@ package gnomod import ( "fmt" - "io/fs" "os" "path/filepath" "strings" - - "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/packages" - "github.com/gnolang/gno/tm2/pkg/std" ) type Pkg struct { @@ -86,72 +81,6 @@ func visitPackage(pkg Pkg, pkgs []Pkg, visited, onStack map[string]bool, sortedP return nil } -// ListPkgs lists all gno packages in the given root directory. -func ListPkgs(root string) (PkgList, error) { - var pkgs []Pkg - - err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - if !d.IsDir() { - return nil - } - gnoModPath := filepath.Join(path, "gno.mod") - data, err := os.ReadFile(gnoModPath) - if os.IsNotExist(err) { - return nil - } - if err != nil { - return err - } - - gnoMod, err := Parse(gnoModPath, data) - if err != nil { - return fmt.Errorf("parse: %w", err) - } - gnoMod.Sanitize() - if err := gnoMod.Validate(); err != nil { - return fmt.Errorf("failed to validate gno.mod in %s: %w", gnoModPath, err) - } - - pkg, err := gnolang.ReadMemPackage(path, gnoMod.Module.Mod.Path) - if err != nil { - // ignore package files on error - pkg = &std.MemPackage{} - } - - importsMap, err := packages.Imports(pkg, nil) - if err != nil { - // ignore imports on error - importsMap = nil - } - importsRaw := importsMap.Merge(packages.FileKindPackageSource, packages.FileKindTest, packages.FileKindXTest) - - imports := make([]string, 0, len(importsRaw)) - for _, imp := range importsRaw { - // remove self and standard libraries from imports - if imp.PkgPath != gnoMod.Module.Mod.Path && - !gnolang.IsStdlib(imp.PkgPath) { - imports = append(imports, imp.PkgPath) - } - } - - pkgs = append(pkgs, Pkg{ - Dir: path, - Name: gnoMod.Module.Mod.Path, - Draft: gnoMod.Draft, - Imports: imports, - }) - return nil - }) - if err != nil { - return nil, err - } - - return pkgs, nil -} - // GetNonDraftPkgs returns packages that are not draft // and have no direct or indirect draft dependencies. func (sp SortedPkgList) GetNonDraftPkgs() SortedPkgList { diff --git a/gnovm/pkg/gnomod/pkg_test.go b/gnovm/pkg/gnomod/pkg_test.go index 7c3035a4b7b..76ceb1395a4 100644 --- a/gnovm/pkg/gnomod/pkg_test.go +++ b/gnovm/pkg/gnomod/pkg_test.go @@ -1,13 +1,16 @@ -package gnomod +package gnomod_test import ( "os" "path/filepath" "testing" - "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/tm2/pkg/testutils" ) func TestListAndNonDraftPkgs(t *testing.T) { @@ -15,7 +18,7 @@ func TestListAndNonDraftPkgs(t *testing.T) { desc string in []struct{ name, modfile string } - outListPkgs []string + outPkgList []string outNonDraftPkgs []string }{ { @@ -37,7 +40,7 @@ func TestListAndNonDraftPkgs(t *testing.T) { `module baz`, }, }, - outListPkgs: []string{"foo", "bar", "baz"}, + outPkgList: []string{"foo", "bar", "baz"}, outNonDraftPkgs: []string{"foo", "bar", "baz"}, }, { @@ -58,7 +61,7 @@ func TestListAndNonDraftPkgs(t *testing.T) { module qux`, }, }, - outListPkgs: []string{"foo", "baz", "qux"}, + outPkgList: []string{"foo", "baz", "qux"}, outNonDraftPkgs: []string{"foo", "baz"}, }, } { @@ -74,11 +77,11 @@ func TestListAndNonDraftPkgs(t *testing.T) { } // List packages - pkgs, err := ListPkgs(dirPath) + pkgs, err := gno.ReadPkgListFromDir(dirPath) require.NoError(t, err) - assert.Equal(t, len(tc.outListPkgs), len(pkgs)) + assert.Equal(t, len(tc.outPkgList), len(pkgs)) for _, p := range pkgs { - assert.Contains(t, tc.outListPkgs, p.Name) + assert.Contains(t, tc.outPkgList, p.Name) } // Sort packages @@ -111,17 +114,17 @@ func createGnoModPkg(t *testing.T, dirPath, pkgName, modData string) { func TestSortPkgs(t *testing.T) { for _, tc := range []struct { desc string - in PkgList + in gnomod.PkgList expected []string shouldErr bool }{ { desc: "empty_input", - in: []Pkg{}, + in: []gnomod.Pkg{}, expected: make([]string, 0), }, { desc: "no_dependencies", - in: []Pkg{ + in: []gnomod.Pkg{ {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{}}, {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{}}, {Name: "pkg3", Dir: "/path/to/pkg3", Imports: []string{}}, @@ -129,20 +132,20 @@ func TestSortPkgs(t *testing.T) { expected: []string{"pkg1", "pkg2", "pkg3"}, }, { desc: "circular_dependencies", - in: []Pkg{ + in: []gnomod.Pkg{ {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{"pkg1"}}, }, shouldErr: true, }, { desc: "missing_dependencies", - in: []Pkg{ + in: []gnomod.Pkg{ {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, }, shouldErr: true, }, { desc: "valid_dependencies", - in: []Pkg{ + in: []gnomod.Pkg{ {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{"pkg3"}}, {Name: "pkg3", Dir: "/path/to/pkg3", Imports: []string{}}, diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index 19b3a3b4c82..46b31b97daf 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -955,7 +955,7 @@ func addLine(x *modfile.FileSyntax, hint modfile.Expr, tokens ...string) *modfil return newl } -func addReplace(syntax *modfile.FileSyntax, replace *[]*modfile.Replace, oldPath, oldVers, newPath, newVers string) error { +func addReplace(syntax *modfile.FileSyntax, replace *[]*modfile.Replace, oldPath, oldVers, newPath, newVers string) { need := true oldv := module.Version{Path: oldPath, Version: oldVers} newv := module.Version{Path: newPath, Version: newVers} @@ -989,5 +989,4 @@ func addReplace(syntax *modfile.FileSyntax, replace *[]*modfile.Replace, oldPath if need { *replace = append(*replace, &modfile.Replace{Old: oldv, New: newv, Syntax: addLine(syntax, hint, tokens...)}) } - return nil } diff --git a/gnovm/pkg/gnomod/read_test.go b/gnovm/pkg/gnomod/read_test.go index d9c35205a51..09a706128d0 100644 --- a/gnovm/pkg/gnomod/read_test.go +++ b/gnovm/pkg/gnomod/read_test.go @@ -105,22 +105,23 @@ func TestParseVersions(t *testing.T) { ok bool }{ // go lines - {desc: "empty", input: "module m\ngo \n", ok: false}, - {desc: "one", input: "module m\ngo 1\n", ok: false}, - {desc: "two", input: "module m\ngo 1.22\n", ok: true}, - {desc: "three", input: "module m\ngo 1.22.333", ok: true}, - {desc: "before", input: "module m\ngo v1.2\n", ok: false}, - {desc: "after", input: "module m\ngo 1.2rc1\n", ok: true}, - {desc: "space", input: "module m\ngo 1.2 3.4\n", ok: false}, - {desc: "alt1", input: "module m\ngo 1.2.3\n", ok: true}, - {desc: "alt2", input: "module m\ngo 1.2rc1\n", ok: true}, - {desc: "alt3", input: "module m\ngo 1.2beta1\n", ok: true}, - {desc: "alt4", input: "module m\ngo 1.2.beta1\n", ok: false}, + {desc: "empty", input: "module m\ngno \n", ok: false}, + {desc: "one", input: "module m\ngno 1\n", ok: false}, + {desc: "two", input: "module m\ngno 1.22\n", ok: true}, + {desc: "two go", input: "module m\ngo 1.22\n", ok: false}, + {desc: "three", input: "module m\ngno 1.22.333", ok: true}, + {desc: "before", input: "module m\ngno v1.2\n", ok: false}, + {desc: "after", input: "module m\ngno 1.2rc1\n", ok: true}, + {desc: "space", input: "module m\ngno 1.2 3.4\n", ok: false}, + {desc: "alt1", input: "module m\ngno 1.2.3\n", ok: true}, + {desc: "alt2", input: "module m\ngno 1.2rc1\n", ok: true}, + {desc: "alt3", input: "module m\ngno 1.2beta1\n", ok: true}, + {desc: "alt4", input: "module m\ngno 1.2.beta1\n", ok: false}, } t.Run("Strict", func(t *testing.T) { for _, test := range tests { t.Run(test.desc, func(t *testing.T) { - if _, err := Parse("gno.mod", []byte(test.input)); err == nil && !test.ok { + if _, err := ParseBytes("gno.mod", []byte(test.input)); err == nil && !test.ok { t.Error("unexpected success") } else if err != nil && test.ok { t.Errorf("unexpected error: %v", err) @@ -169,7 +170,7 @@ comments before "// e" }, } { t.Run(test.desc, func(t *testing.T) { - f, err := Parse("gno.mod", []byte(test.input)) + f, err := ParseBytes("gno.mod", []byte(test.input)) if err != nil { t.Fatal(err) } @@ -210,7 +211,33 @@ comments before "// e" } } -var addModuleStmtTests = []struct { +var setGnoTests = []struct { + desc string + in string + version string + out string +}{ + { + `existing`, + ` + gno 0.0 + `, + "0.9", + ` + gno 0.9 + `, + }, + { + `new`, + ``, + "0.9", + ` + gno 0.9 + `, + }, +} + +var setModuleTests = []struct { desc string in string path string @@ -312,13 +339,25 @@ var dropReplaceTests = []struct { }, } -func TestAddModuleStmt(t *testing.T) { - for _, tt := range addModuleStmtTests { +func TestSetGno(t *testing.T) { + for _, tt := range setGnoTests { t.Run(tt.desc, func(t *testing.T) { testEdit(t, tt.in, tt.out, func(f *File) error { - err := f.AddModuleStmt(tt.path) + f.SetGno(tt.version) f.Syntax.Cleanup() - return err + return nil + }) + }) + } +} + +func TestSetModule(t *testing.T) { + for _, tt := range setModuleTests { + t.Run(tt.desc, func(t *testing.T) { + testEdit(t, tt.in, tt.out, func(f *File) error { + f.SetModule(tt.path) + f.Syntax.Cleanup() + return nil }) }) } @@ -340,9 +379,9 @@ func TestDropReplace(t *testing.T) { for _, tt := range dropReplaceTests { t.Run(tt.desc, func(t *testing.T) { testEdit(t, tt.in, tt.out, func(f *File) error { - err := f.DropReplace(tt.path, tt.vers) + f.DropReplace(tt.path, tt.vers) f.Syntax.Cleanup() - return err + return nil }) }) } @@ -350,11 +389,11 @@ func TestDropReplace(t *testing.T) { func testEdit(t *testing.T, in, want string, transform func(f *File) error) *File { t.Helper() - f, err := Parse("in", []byte(in)) + f, err := ParseBytes("in", []byte(in)) if err != nil { t.Fatal(err) } - g, err := Parse("out", []byte(want)) + g, err := ParseBytes("out", []byte(want)) if err != nil { t.Fatal(err) } diff --git a/gnovm/pkg/gnomod/utils.go b/gnovm/pkg/gnomod/utils.go index fe1d0ed79be..ba352576390 100644 --- a/gnovm/pkg/gnomod/utils.go +++ b/gnovm/pkg/gnomod/utils.go @@ -4,6 +4,9 @@ import ( "errors" "os" "path/filepath" + "testing" + + "github.com/stretchr/testify/require" ) // ErrGnoModNotFound is returned by [FindRootDir] when, even after traversing @@ -34,3 +37,16 @@ func FindRootDir(absPath string) (string, error) { return "", ErrGnoModNotFound } + +func createGnoModPkg(t *testing.T, dirPath, pkgName, modData string) { + t.Helper() + + // Create package dir + pkgDirPath := filepath.Join(dirPath, pkgName) + err := os.MkdirAll(pkgDirPath, 0o755) + require.NoError(t, err) + + // Create gno.mod + err = os.WriteFile(filepath.Join(pkgDirPath, "gno.mod"), []byte(modData), 0o644) + require.NoError(t, err) +} diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index 06f1ce30fc9..c49dbab6617 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -236,6 +236,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ + {Name: "gno.mod", Body: "gno 0.9"}, {Name: filename, Body: string(content)}, }, }); err != nil { @@ -278,10 +279,8 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ - { - Name: filename, - Body: string(content), - }, + {Name: "gno.mod", Body: "gno 0.9"}, + {Name: filename, Body: string(content)}, }, } // Validate Gno syntax and type check. @@ -313,10 +312,8 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ - { - Name: filename, - Body: string(content), - }, + {Name: "gno.mod", Body: "gno 0.9"}, + {Name: filename, Body: string(content)}, }, } orig, tx := m.Store, m.Store.BeginTransaction(nil, nil, nil) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 7c04acb8a67..e5d584fee55 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -59,6 +59,12 @@ func StoreWithOptions( if opts.PreprocessOnly { processMemPackage = func(m *gno.Machine, memPkg *std.MemPackage, save bool) (*gno.PackageNode, *gno.PackageValue) { m.Store.AddMemPackage(memPkg) + /* NOTE: Don't pre-transpile here, just gno lint the test files and fix them. + _, _, err := gno.PretranspileToGno0p9(memPkg, false) // no need for _test.gno or _filetest.gno files. + if err != nil { + panic("error pretranspiling to Gno 0.9: " + err.Error()) + } + */ return m.PreprocessFiles(memPkg.Name, memPkg.Path, gno.ParseMemPackage(memPkg), save, false) } } diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index b075d193030..9183877733c 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -9,6 +9,12 @@ import ( "strings" ) +// A MemFile is the simplest representation of a "file". +// +// Notice it doesn't have owners or timestamps. Keep this as is for +// portability. Not even date created, ownership, or other attributes. Just a +// name, and a body. This keeps things portable, easy to hash (otherwise need +// to manage e.g. the encoding and portability of timestamps). type MemFile struct { Name string `json:"name" yaml:"name"` Body string `json:"body" yaml:"body"` @@ -21,9 +27,9 @@ type MemFile struct { // NOTE: in the future, a MemPackage may represent // updates/additional-files for an existing package. type MemPackage struct { - Name string `json:"name" yaml:"name"` // package name as declared by `package` - Path string `json:"path" yaml:"path"` // import path - Files []*MemFile `json:"files" yaml:"files"` + Name string `json:"name" yaml:"name"` // package name as declared by `package` + Path string `json:"path" yaml:"path"` // import path + Files []*MemFile `json:"files" yaml:"files"` // plain file system files. } const pathLengthLimit = 256 @@ -94,7 +100,7 @@ func (mpkg *MemPackage) IsEmpty() bool { func (mpkg *MemPackage) WriteTo(dirPath string) error { for _, file := range mpkg.Files { - fmt.Println("FORMATTED:", file.Name, file.Body) + fmt.Printf("MemPackage.WriteTo(%s) (%d) bytes written\n", file.Name, len(file.Body)) fpath := filepath.Join(dirPath, file.Name) err := ioutil.WriteFile(fpath, []byte(file.Body), 0644) if err != nil { From 17faaca6bf9741dc61a062cd84e6097c300bd004 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 10 May 2025 05:26:29 -0700 Subject: [PATCH 06/83] improve flow and documentation --- gnovm/cmd/gno/tool_lint.go | 161 +++++++++++++++++--------- gnovm/pkg/gnolang/gotypecheck.go | 102 ++++++++-------- gnovm/pkg/gnolang/transpile_gno0p9.go | 147 +++++++++++------------ gnovm/pkg/gnolang/version.go | 1 + gnovm/pkg/test/filetest.go | 4 +- 5 files changed, 234 insertions(+), 181 deletions(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 67fc91c384a..702b812405c 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -5,7 +5,9 @@ import ( "errors" "flag" "fmt" + "go/ast" "go/scanner" + "go/token" "go/types" goio "io" "os" @@ -111,11 +113,10 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir, goio.Discard, test.StoreOptions{PreprocessOnly: true}, ) - ppkgs := map[string]processedPackage{} //---------------------------------------- - // STEP 1: PREPROCESS ALL FILES + // STAGE 1: for _, dir := range dirs { if verbose { io.ErrPrintln(dir) @@ -127,13 +128,13 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } // TODO: This should be handled by ReadMemPackage. - fname := path.Join(dir, "gno.mod") - gmf, err := gnomod.ParseFilepath(fname) + fpath := path.Join(dir, "gno.mod") + mod, err := gnomod.ParseFilepath(fpath) if err != nil { issue := lintIssue{ Code: lintGnoMod, Confidence: 1, // ?? - Location: fname, + Location: fpath, Msg: err.Error(), } io.ErrPrintln(issue) @@ -141,8 +142,9 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { continue } + // STEP 1: ReadMemPackage() // Read MemPackage with pkgPath. - pkgPath, _ := determinePkgPath(gmf, dir, cfg.rootDir) + pkgPath, _ := determinePkgPath(mod, dir, cfg.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { io.ErrPrintln(issueFromError( @@ -166,18 +168,28 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { cw := bs.CacheWrap() gs := ts.BeginTransaction(cw, cw, nil) + // These are Go types. + var pkg *token.Package + var fset *token.FileSet + var astfs []*ast.File + var errs error + // Run type checking - if gmf == nil || !gmf.Draft { - // NOTE: - // lintTypeCheck() --> - // TypeCheckMemPackageTest() --> - // imp.parseCheckMemPackage() --> - // PretranspileToGno0p9() - // That is, it will pre-transpile if needed. - foundErr, err := lintTypeCheck( - io, dir, mpkg, gs) - if err != nil { - io.ErrPrintln(err) + if mod == nil || !mod.Draft { + // STEP 2: ParseGnoMod() + // STEP 3: GoParse*() + // + // typeCheckAndPrintErrors(mpkg) --> + // TypeCheckMemPackage(mpkg) --> + // imp.typeCheckMemPackage(mpkg) + // ParseGnoMod(mpkg); + // GoParseMemPackage(mpkg); + // g.cfg.Check(); + // + // NOTE: Prepare*() is not called. + pkg, fset, astfs, errs = typeCheckAndPrintErrors(io, dir, mpkg, gs) + if errs != nil { + io.ErrPrintln(errs) hasError = true } else if foundErr { hasError = true @@ -186,43 +198,50 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } - // Construct machine for testing. - tm := test.Machine(gs, goio.Discard, pkgPath, false) - defer tm.Release() + // STEP 4 & 5: Prepare*() and Preprocess*(). + { + // Construct machine for testing. + tm := test.Machine(gs, goio.Discard, pkgPath, false) + defer tm.Release() - // Check test files - all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + // Gno parse source fileset and test filesets. + all, fset2, _tests, ftests := sourceAndTestFileset(mpkg) - // Preprocess fset files (w/ some _test.gno). - pn, _ := tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) - // Preprocess _test files (all _test.gno). - for _, fset := range _tests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) - } - // Preprocess _filetest.gno files. - for _, fset := range ftests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) + // Prepare Go AST for preprocessing. + errs := PrepareGno0p9(fset, astfs) + if errs != nil { + io.ErrPrintln(errs) + hasError = true + } + + // Preprocess fset files (w/ some _test.gno). + pn, _ := tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset2, false, false) + // Preprocess _test files (all _test.gno). + for _, fset3 := range _tests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset3, false, false) + } + // Preprocess _filetest.gno files. + for _, fset3 := range ftests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset3, false, false) + } } + // Record results. ppkgs[dir] = processedPackage{ mpkg, fset, pn, _tests, ftests} - // Get the gno.mod file. - gmf, err := gnomod.ParseMemPackage(mpkg) - if err != nil { - io.ErrPrintln(err) - hasError = true - } - // Before Gno 0.9 is Gno 0.0 (no "gno 0.9" in gno.mod) - if gmf.Gno.Version == "0.0" { + + // STEP 6: FindXItems(): + // FindXItems for all files if outdated. + if mod.Gno.Version == "0.0" { // Use the preprocessor to collect the // transformations needed to be done. // They are collected in // pn.GetAttribute("XREALMITEM") for _, fn := range all.Files { - gno.FindGno0p9XItems(gs, pn, fn) + gno.FindXItemsGno0p9(gs, pn, fn) } } }) @@ -232,7 +251,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } //---------------------------------------- - // STEP 2: TRANSFORM FOR Gno 0.9 + // STAGE 2: Transpile to Gno 0.9 + // Must be a separate stage because dirs depend on each other. for _, dir := range dirs { ppkg, ok := ppkgs[dir] if !ok { @@ -240,27 +260,55 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } mpkg, pn := ppkg.mpkg, ppkg.pn xform, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) - err := gno.TranspileToGno0p9(mpkg, dir, xform) + + // STEP 7 & 8: gno.TranspileGno0p9() Part 1 & 2 + err := gno.TranspileGno0p9(mpkg, dir, xform) if err != nil { - panic(err) + return err } } - if hasError { return commands.ExitCodeError(1) } + //---------------------------------------- + // STAGE 3: Write. + // Must be a separate stage to prevent partial writes. + for _, dir := range dirs { + ppkg, ok := ppkgs[dir] + if !ok { + panic("where did it go") + } + + // STEP 9: mpkg.WriteTo(): + err := ppkg.mpkg.WriteTo(dir) + if err != nil { + return err + } + } + return nil } -func lintTypeCheck(io commands.IO, dir string, mpkg *std.MemPackage, testStore gno.Store) (errorsFound bool, err error) { - tcErr := gno.TypeCheckMemPackageTest(mpkg, testStore) - if tcErr == nil { - return false, nil +// Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). +func typeCheckAndPrintErrors( + io commands.IO, + dir string, + mpkg *std.MemPackage, + testStore gno.Store, +) ( + pkg *token.Package, + fset *token.FileSet, + astfs []*ast.File, + errs error) { + + pkg, fset, astfs, errs = gno.TypeCheckMemPackage(mpkg, testStore) + if errs != nil { + return } - errs := multierr.Errors(tcErr) - for _, err := range errs { + errors := multierr.Errors(errs) + for _, err := range errors { switch err := err.(type) { case types.Error: loc := err.Fset.Position(err.Pos).String() @@ -292,13 +340,14 @@ func lintTypeCheck(io commands.IO, dir string, mpkg *std.MemPackage, testStore g Location: loc, }) default: - return false, fmt.Errorf("unexpected error type: %T", err) + errs = fmt.Errorf("unexpected error type; %T", err) + return } } - return true, nil + return } -// Sorts mpkg files into the following filesets: +// Gno parses and sorts mpkg files into the following filesets: // - all: all files // - fset: all normal and _test.go files in package excluding `package xxx_test` // integration *_test.gno files. diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 075dd875e8c..9e823dfa48b 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -4,6 +4,7 @@ import ( "fmt" "go/ast" "go/parser" + "go/token" "go/types" "path" "slices" @@ -12,7 +13,7 @@ import ( "go.uber.org/multierr" ) -// type checking (using go/types) +// Type-checking (using go/types) // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. @@ -24,24 +25,16 @@ type MemPackageGetter interface { // mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. -func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) error { - return typeCheckMemPackage(mpkg, getter, false) -} +// TODO: rename these to GoTypeCheck*, goTypeCheck*... +func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( + pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { -// TypeCheckMemPackageTest performs the same type checks as -// [TypeCheckMemPackage], but allows re-declarations. -// -// NOTE: like TypeCheckMemPackage, this function ignores tests and filetests. -func TypeCheckMemPackageTest(mpkg *std.MemPackage, getter MemPackageGetter) error { - return typeCheckMemPackage(mpkg, getter, true) + return typeCheckMemPackage(mpkg, getter) } -func typeCheckMemPackage( - mpkg *std.MemPackage, - getter MemPackageGetter, - testing bool) error { +func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( + pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { - var errs error imp := &gnoImporter{ getter: getter, cache: map[string]gnoImporterResult{}, @@ -50,17 +43,12 @@ func typeCheckMemPackage( errs = multierr.Append(errs, err) }, }, - allowRedefinitions: testing, + withTests: true, } imp.cfg.Importer = imp - _, err := imp.parseCheckMemPackage(mpkg) - // prefer to return errs instead of err: - // err will generally contain only the first error encountered. - if errs != nil { - return errs - } - return err + pkg, fset, astfs, errs = imp.typeCheckMemPackage(mpkg) + return } type gnoImporterResult struct { @@ -69,12 +57,10 @@ type gnoImporterResult struct { } type gnoImporter struct { - getter MemPackageGetter - cache map[string]gnoImporterResult - cfg *types.Config - - // allow symbol redefinitions? (test standard libraries) - allowRedefinitions bool + getter MemPackageGetter + cache map[string]gnoImporterResult + cfg *types.Config + withTests bool } // Unused, but satisfies the Importer interface. @@ -98,21 +84,30 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac g.cache[path] = gnoImporterResult{err: err} return nil, err } - result, err := g.parseCheckMemPackage(mpkg) - g.cache[path] = gnoImporterResult{pkg: result, err: err} - return result, err + pkg, _, _, errs := g.typeCheckMemPackage(mpkg) + g.cache[path] = gnoImporterResult{pkg: pkg, err: errs} + return pkg, errs } -func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage) (*types.Package, error) { +// Assumes that the code is Gno 0.9. +// If not, first use `gno lint` to transpile the code. +// Returns parsed *types.Package, *token.FileSet, []*ast.File. +func (g *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage) ( + pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { - /* NOTE: Don't pre-transpile here; `gno lint` and fix the source first. - fset, astfs, err := PretranspileToGno0p9(mpkg, false) - if err != nil { - return nil, err + // STEP 1: Check gno.mod version. + _, outdated := ParseGnoMod(mpkg) + if outdated { + return nil, nil, nil, fmt.Errorf("outdated gno version for package %s", mpkg.Path) } - */ - // Add builtins file. + // STEP 2: Parse the mem package to Go AST. + fset, astfs, errs = GoParseMemPackage(mpkg, g.withTests) + if errs != nil { + return nil, nil, nil, fmt.Errorf("go parsing mem package: %v", errs) + } + + // STEP 2: Add .gnobuiltins.go file. file := &std.MemFile{ Name: ".gnobuiltins.go", Body: fmt.Sprintf(`package %s @@ -124,25 +119,28 @@ func revive[F any](fn F) any { return nil } // shim type realm interface{} // shim `, mpkg.Name), } - const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - astf, err := parser.ParseFile(fset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) + + // STEP 2: Parse .gnobuiltins.go file. + const parseOpts = parser.ParseComments | + parser.DeclarationErrors | + parser.SkipObjectResolution + var astf, err = parser.ParseFile( + fset, + path.Join(mpkg.Path, file.Name), + file.Body, + parseOpts) if err != nil { panic("error parsing gotypecheck gnobuiltins.go file") } astfs = append(astfs, astf) - // Type-check pre-transpiled Gno0.9 AST in Go. - // We don't (post)-transpile because the linter - // is supposed to be used to write to the files. - // (No need to support JIT transpiling for imports) - // - // XXX The pre pre thing for @cross. - pkg, err := g.cfg.Check(mpkg.Path, fset, astfs, nil) - return pkg, err + // STEP 3: Type-check Gno0.9 AST in Go. + pkg, errs = g.cfg.Check(mpkg.Path, fset, astfs, nil) + return pkg, fset, astfs, errs } -func deleteOldIdents(idents map[string]func(), f *ast.File) { - for _, decl := range f.Decls { +func deleteOldIdents(idents map[string]func(), astf *ast.File) { + for _, decl := range astf.Decls { fd, ok := decl.(*ast.FuncDecl) // ignore methods and init functions //nolint:goconst @@ -159,7 +157,7 @@ func deleteOldIdents(idents map[string]func(), f *ast.File) { // NOTE: cannot use the index as a file may contain // multiple decls to be removed, so removing one would // make all "later" indexes wrong. - f.Decls = slices.DeleteFunc(f.Decls, + astf.Decls = slices.DeleteFunc(astf.Decls, func(d ast.Decl) bool { return decl == d }) } } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 4cd6d1678e0..46b669c3616 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -9,7 +9,6 @@ import ( "go/parser" "go/token" "path" - "reflect" "strings" "go.uber.org/multierr" @@ -19,42 +18,57 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) +// ======================================== /* -The stages of Gno 0.0 --> Gno 0.9 transpiling. - - - ParseGnoMod: parse gno.mod (if any) and compare versions. - - GoParse: parse Gno to Go AST with go/parser. - - Prepare: minimal Go AST mutations for Gno VM compat. - - Find xitems: Gno AST static analaysis to produce xitems. - - Rekey xitems: re-key xitems by Go Node before line changes. - - Transpile: main Go AST mutations for Gno upgrade. -*/ +The steps of Gno 0.0 --> Gno 0.9 transpiling. + 1. GetMemPackage, ReadMemPackage, .... + 2. ParseGnoMod(): parse gno.mod (if any) and compare versions. + 3. GoParse*(): parse Gno to Go AST with go/parser. + 4. Prepare*(): minimal Go AST mutations for Gno VM compat. + 5. m.PreprocessFiles(): normal Gno AST preprocessing. + 6. FindXItems*(): Gno AST static analaysis to produce xitems. + 7. Transpile*() Part 1: re-key xitems by Go Node before step 2 line changes. + 8. Transpile*() Part 2: main Go AST mutations for Gno upgrade. + 9. mpkg.WriteTo(): write mem package to disk. + +In cmd/gno/tool_lint.go each step is grouped into stages for all dirs: + * Stage 1: (for all dirs) + 1. gno.ReadMemPackage() + 2. gno.TypeCheckMemPackage() > ParseGnoMod() + 3. gno.TypeCheckMemPackage() > GoParseMemPackage() + gno.TypeCheckMemPackage() > g.cfg.Check() + 4. PrepareGno0p9() + 5. tm.PreprocessFiles() + 6. gno.FindXItemsGno0p9() + * Stage 2: + 7. gno.TranspileGno0p9() Part 1 + 8. gno.TranspileGno0p9() Part 2 + * Stage 3: + 9. mpkg.WriteTo() + +In gotypecheck.go, TypeCheck*() diverges at step 4 and terminates: + 1. mpkg provided as argument + 2. ParseGnoMod() + 3. GoParseMemPackage() + 4. g.cfg.Check(): Go type-checker + +*/ // ======================================== -// Parses the appropriate gno.mod file from mpkg or -// generates a default one. -// -// Args: -// - testing: if running tests -// - linting: if running `gno lint` transpiling. +// Parses the gno.mod file from mpkg. +// To generate default ones, use: +// `mod, _ = gnomod.ParseBytes(gnomodDefault)` // // Results: -// - mod: the gno.mod file. +// - mod: the gno.mod file, or nil if not found. // - outdated: true if it should be transpiled to the current version. -func ParseGnoMod(mpkg *MemPackage, testing, linting bool) ( - mod *gnomod.File, outdated bool) { - - if testing { - // If we are testing we assume files already conform to the - // latest version. If they don't, run `gno lint` first before - // running tests. - mod, _ = gnomod.ParseBytes(gnomodTesting) - } else if IsStdlib(mpkg.Path) { +func ParseGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, outdated bool) { + if IsStdlib(mpkg.Path) { // stdlib/extern packages are assumed up to date. - mod, _ = gnomod.ParseBytes(gnomodTesting) + mod, _ = gnomod.ParseBytes("/gno.mod", []byte(gnomodLatest)) } else if mod, _ = gnomod.ParseMemPackage(mpkg); mod == nil { // gno.mod doesn't exist. - mod, _ = gnomod.ParseBytes(gnomodDefault) + mod, _ = gnomod.ParseBytes(mpkg.Path+"/gno.mod", []byte(gnomodDefault)) outdated = true } else if mod.Gno == nil { // 'gno 0.9' was never specified, continue @@ -75,7 +89,7 @@ func ParseGnoMod(mpkg *MemPackage, testing, linting bool) ( // - withTests: if true also parses and includes all *_test.gno // and *_filetest.gno files. func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( - fset *token.FileSet, astfs []*ast.File, err error) { + fset *token.FileSet, astfs []*ast.File, errs error) { fset = token.NewFileSet() // This map is used to allow for function re-definitions, which are @@ -113,48 +127,42 @@ func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( // The *ast.File passed all filters. astfs = append(astfs, astf) } + if errs != nil { + return fset, astfs, errs + } // END processing all files. - return fset, astfs, nil + return } // ======================================== // Prepare Gno 0.0 for Gno 0.9. // // When Gno syntax breaks in higher versions, existing code must first be -// pre-transcribed such that the Gno preprocessor won't panic. This allows -// old Gno code to be preprocessed and used by the Gno VM for static analysis. -// More transpiling will happen later after the preprocessed Gno AST is -// scanned for mutations on the Go AST which follows. +// pre-transcribed such that the Gno preprocessor won't panic. This allows old +// Gno code to be preprocessed and used by the Gno VM for static analysis. +// More transpiling will happen later after the preprocessed Gno AST is scanned +// for mutations on the Go AST which follows. Any changes are applied directly +// on the mem package. // -// - renames 'realm' to 'realm_' to avoid conflict with new uverse type. +// * Renames 'realm' to 'realm_' to avoid conflict with new uverse type. // -// Any changes are applied directly on the mem package. -// Errors are returned in aggregate as a multierr type. -func PrepareGno0p9(mpkg *std.MemPackage) (errs error) { - for _, file := range mpkg.Files { +// Results: +// - errs: returned in aggregate as a multierr type. +func PrepareGno0p9(fset *token.FileSet, astfs []*ast.File) (errs error) { + for _, astf := range astfs { // AST transform for Gno 0.9. - err := pretranspileToGno0p9( - mpkg.Path, fset, file.Name, astf) + err := prepareGno0p9(astf) if err != nil { errs = multierr.Append(errs, err) continue } - // Write formatted AST to mem file. - var buf bytes.Buffer - err = gofmt.Node(&buf, fset, astf) - if err != nil { - errs = multierr.Append(errs, err) - continue - } - file.Body = buf.String() } return } -// Pre-transpile AST mutation(s) for Gno 0.9. -func pretranspileGno0p9(f *ast.File) (err error) { - - // Rename name to _realm to avoid conflict with new builtin "realm". +// Minimal AST mutation(s) for Gno 0.9. +// - Renames 'realm' to '_realm' to avoid conflict with new builtin "realm". +func prepareGno0p9(f *ast.File) (err error) { astutil.Apply(f, func(c *astutil.Cursor) bool { switch n := c.Node().(type) { case *ast.Ident: @@ -189,10 +197,6 @@ func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { defer doRecover(stack, n) - if debug { - debug.Printf("FindXItems %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) - } - switch stage { // ---------------------------------------- case TRANS_BLOCK: @@ -306,8 +310,7 @@ func addXItem(n Node, t string, p string, f string, l int, c int) { } // ======================================== -// Transpiles existing Gno code to Gno 0.9, the one with @cross decorators, -// not cross(fn)(...). +// Transpiles existing Gno code to Gno 0.9. // // Writes in place if dir is provided. Transpiled packages will have their // gno.mod Gno version to 0.9. @@ -315,12 +318,12 @@ func addXItem(n Node, t string, p string, f string, l int, c int) { // Args: // - dir: where to write to. // - xform: result of FindGno0p9XItems(). -func TranspileToGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) error { +func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) error { // Return if gno.mod is current. var mod *gnomod.File var outdated bool = false - mod, outdated = parseGnoModFile(mpkg, false, true) + mod, outdated = ParseGnoMod(mpkg) if !outdated { return nil // already up-to-date. } @@ -355,19 +358,18 @@ func TranspileToGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string errs = multierr.Append(errs, err) continue } - deleteOldIdents(delFunc, astf) - // AST transform for Gno 0.9 (step 1) - xform2, err := transpileToGno0p9_step1(mpkg.Path, fset, file.Name, astf, xform) + // Transpile Part 1: re-key xform by ast.Node. + xform2, err := transpileGno0p9_part1(mpkg.Path, fset, file.Name, astf, xform) if err != nil { errs = multierr.Append(errs, err) continue } - // AST transform for Gno 0.9 (step 2) - if err := transpileToGno0p9_step2(mpkg.Path, fset, file.Name, astf, xform2); err != nil { + // Transpile Part 2: main Go AST transform for Gno 0.9. + if err := transpileGno0p9_part2(mpkg.Path, fset, file.Name, astf, xform2); err != nil { errs = multierr.Append(errs, err) continue } - // Write transformed AST to Go to file. + // Write transformed AST to Go to mem file. var buf bytes.Buffer err = gofmt.Node(&buf, fset, astf) if err != nil { @@ -381,20 +383,22 @@ func TranspileToGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string } // END processing all files. - // Write version to mod and to mpkg/gno.mod. + // Write version to mod and to mem file named "gno.mod". mod.SetGno(GnoVersion) mf := mpkg.GetFile("gno.mod") mf.Body = mod.WriteString() - // Write mpkg/* to dir. + // Write mem package to dir. err := mpkg.WriteTo(dir) return err } +// Transpile Step 1: re-key xform by ast.Node. +// // We can't just apply as we encounter matches in xform unfortunately because // it causes the lines to shift. So we first convert xform into a map keyed // by node and then do the actual transpiling in step 2. -func transpileToGno0p9_step1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[string]string) (xform2 map[ast.Node]string, err error) { +func transpileGno0p9_part1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[string]string) (xform2 map[ast.Node]string, err error) { xform2 = make(map[ast.Node]string, len(xform)) astutil.Apply(f, func(c *astutil.Cursor) bool { @@ -436,7 +440,8 @@ func transpileToGno0p9_step1(pkgPath string, fs *token.FileSet, fname string, f return xform2, err } -func transpileToGno0p9_step2(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[ast.Node]string) (err error) { +// The main Go AST transpiling logic to make Gno code Gno 0.9. +func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[ast.Node]string) (err error) { var lastLine = 0 var didRemoveCrossing = false diff --git a/gnovm/pkg/gnolang/version.go b/gnovm/pkg/gnolang/version.go index 85af860e7d5..91f36b080d3 100644 --- a/gnovm/pkg/gnolang/version.go +++ b/gnovm/pkg/gnolang/version.go @@ -6,6 +6,7 @@ const ( const ( // gno.mod files assumed in testing/default contexts. + gnomodLatest = `go 0.9` // when gno.mod is missing for stdlibs. gnomodTesting = `go 0.9` // when gno.mod is missing while testing. gnomodDefault = `go 0.0` // when gno.mod is missing in general. ) diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index c49dbab6617..c346d90e534 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -284,7 +284,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte }, } // Validate Gno syntax and type check. - if err := gno.TypeCheckMemPackageTest(memPkg, m.Store); err != nil { + if _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } @@ -320,7 +320,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte m.Store = tx // Validate Gno syntax and type check. - if err := gno.TypeCheckMemPackageTest(memPkg, m.Store); err != nil { + if _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } From 4fc804c3fa83869f77a33250af2206697394afee Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 10 May 2025 13:06:56 -0700 Subject: [PATCH 07/83] gimp --- gnovm/pkg/gnolang/gotypecheck.go | 34 +++++++++++++++++---------- gnovm/pkg/gnolang/transpile_gno0p9.go | 9 +++---- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 9e823dfa48b..68cfe89dc90 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -35,7 +35,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { - imp := &gnoImporter{ + gimp := &gnoImporter{ getter: getter, cache: map[string]gnoImporterResult{}, cfg: &types.Config{ @@ -43,11 +43,11 @@ func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( errs = multierr.Append(errs, err) }, }, - withTests: true, } - imp.cfg.Importer = imp + gimp.cfg.Importer = gimp - pkg, fset, astfs, errs = imp.typeCheckMemPackage(mpkg) + wtests := true // type check all .gno files. + pkg, fset, astfs, errs = gimp.typeCheckMemPackage(mpkg, wtests) return } @@ -56,16 +56,19 @@ type gnoImporterResult struct { err error } +// gimp. +// gimp type checks. +// gimp remembers. +// gimp. type gnoImporter struct { - getter MemPackageGetter - cache map[string]gnoImporterResult - cfg *types.Config - withTests bool + getter MemPackageGetter + cache map[string]gnoImporterResult + cfg *types.Config } // Unused, but satisfies the Importer interface. -func (g *gnoImporter) Import(path string) (*types.Package, error) { - return g.ImportFrom(path, "", 0) +func (gimp *gnoImporter) Import(path string) (*types.Package, error) { + return gimp.ImportFrom(path, "", 0) } type importNotFoundError string @@ -78,13 +81,15 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac if pkg, ok := g.cache[path]; ok { return pkg.pkg, pkg.err } + // fmt.Println("GNOIMPORTER IMPORTFROM > GETMEMPACKAGE", path) mpkg := g.getter.GetMemPackage(path) if mpkg == nil { err := importNotFoundError(path) g.cache[path] = gnoImporterResult{err: err} return nil, err } - pkg, _, _, errs := g.typeCheckMemPackage(mpkg) + wtests := false // don't parse test files for imports. + pkg, _, _, errs := g.typeCheckMemPackage(mpkg, wtests) g.cache[path] = gnoImporterResult{pkg: pkg, err: errs} return pkg, errs } @@ -92,7 +97,10 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac // Assumes that the code is Gno 0.9. // If not, first use `gno lint` to transpile the code. // Returns parsed *types.Package, *token.FileSet, []*ast.File. -func (g *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage) ( +// +// Args: +// - wtests: if true, with all *_test.gno and *_testfile.gno files. +func (g *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, wtests bool) ( pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { // STEP 1: Check gno.mod version. @@ -102,7 +110,7 @@ func (g *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage) ( } // STEP 2: Parse the mem package to Go AST. - fset, astfs, errs = GoParseMemPackage(mpkg, g.withTests) + fset, astfs, errs = GoParseMemPackage(mpkg, wtests) if errs != nil { return nil, nil, nil, fmt.Errorf("go parsing mem package: %v", errs) } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 46b669c3616..f61638674d3 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -86,9 +86,9 @@ func ParseGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, outdated bool) { // []ast.File with `go/parser`. // // Args: -// - withTests: if true also parses and includes all *_test.gno +// - wtests: if true also parses and includes all *_test.gno // and *_filetest.gno files. -func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( +func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( fset *token.FileSet, astfs []*ast.File, errs error) { fset = token.NewFileSet() @@ -104,8 +104,8 @@ func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( if !strings.HasSuffix(file.Name, ".gno") { continue } - // Ignore _test/_filetest.gno files unless withTests. - if !withTests && + // Ignore _test/_filetest.gno files unless wtests. + if !wtests && (false || strings.HasSuffix(file.Name, "_test.gno") || strings.HasSuffix(file.Name, "_filetest.gno")) { @@ -115,6 +115,7 @@ func GoParseMemPackage(mpkg *std.MemPackage, withTests bool) ( const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution + // fmt.Println("GO/PARSER", mpkg.Path, file.Name) var astf, err = parser.ParseFile( fset, path.Join(mpkg.Path, file.Name), file.Body, From 77e5e286004a0f9fef38bed2d5b14c2081d07579 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 10 May 2025 18:15:11 -0700 Subject: [PATCH 08/83] fix multi error passthrough --- gnovm/cmd/gno/tool_lint.go | 4 --- gnovm/pkg/gnolang/gotypecheck.go | 60 ++++++++++++++++++-------------- gnovm/tests/files/switch13.gno | 2 +- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 702b812405c..ab1aaba6fa6 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -303,10 +303,6 @@ func typeCheckAndPrintErrors( errs error) { pkg, fset, astfs, errs = gno.TypeCheckMemPackage(mpkg, testStore) - if errs != nil { - return - } - errors := multierr.Errors(errs) for _, err := range errors { switch err := err.(type) { diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 68cfe89dc90..062fe7cd7cf 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -28,26 +28,22 @@ type MemPackageGetter interface { // TODO: rename these to GoTypeCheck*, goTypeCheck*... func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { - - return typeCheckMemPackage(mpkg, getter) -} - -func typeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( - pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { - - gimp := &gnoImporter{ + var gimp *gnoImporter + gimp = &gnoImporter{ getter: getter, cache: map[string]gnoImporterResult{}, cfg: &types.Config{ Error: func(err error) { - errs = multierr.Append(errs, err) + gimp.Error(err) }, }, + errors: nil, } gimp.cfg.Importer = gimp - wtests := true // type check all .gno files. - pkg, fset, astfs, errs = gimp.typeCheckMemPackage(mpkg, wtests) + all := true // type check all .gno files for mpkg (not for imports). + strict := true // check gno.mod exists + pkg, fset, astfs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) return } @@ -64,6 +60,7 @@ type gnoImporter struct { getter MemPackageGetter cache map[string]gnoImporterResult cfg *types.Config + errors error // multierr } // Unused, but satisfies the Importer interface. @@ -71,26 +68,32 @@ func (gimp *gnoImporter) Import(path string) (*types.Package, error) { return gimp.ImportFrom(path, "", 0) } +// Pass through to cfg.Error for collecting all type-checking errors. +func (gimp *gnoImporter) Error(err error) { + gimp.errors = multierr.Append(gimp.errors, err) +} + type importNotFoundError string func (e importNotFoundError) Error() string { return "import not found: " + string(e) } // ImportFrom returns the imported package for the given import // path when imported by a package file located in dir. -func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Package, error) { - if pkg, ok := g.cache[path]; ok { +func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Package, error) { + if pkg, ok := gimp.cache[path]; ok { return pkg.pkg, pkg.err } // fmt.Println("GNOIMPORTER IMPORTFROM > GETMEMPACKAGE", path) - mpkg := g.getter.GetMemPackage(path) + mpkg := gimp.getter.GetMemPackage(path) if mpkg == nil { err := importNotFoundError(path) - g.cache[path] = gnoImporterResult{err: err} + gimp.cache[path] = gnoImporterResult{err: err} return nil, err } - wtests := false // don't parse test files for imports. - pkg, _, _, errs := g.typeCheckMemPackage(mpkg, wtests) - g.cache[path] = gnoImporterResult{pkg: pkg, err: errs} + all := false // don't parse test files for imports. + strict := false // don't check for gno.mod for imports. + pkg, _, _, errs := gimp.typeCheckMemPackage(mpkg, all, strict) + gimp.cache[path] = gnoImporterResult{pkg: pkg, err: errs} return pkg, errs } @@ -99,18 +102,23 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac // Returns parsed *types.Package, *token.FileSet, []*ast.File. // // Args: -// - wtests: if true, with all *_test.gno and *_testfile.gno files. -func (g *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, wtests bool) ( +// - all: If true add all *_test.gno and *_testfile.gno files. +// Generally should be set to false when importing because +// tests cannot be imported and used anyways. +// - strict: If true errors on gno.mod version mismatch. +func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, strict bool) ( pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { // STEP 1: Check gno.mod version. - _, outdated := ParseGnoMod(mpkg) - if outdated { - return nil, nil, nil, fmt.Errorf("outdated gno version for package %s", mpkg.Path) + if strict { + _, outdated := ParseGnoMod(mpkg) + if outdated { + return nil, nil, nil, fmt.Errorf("outdated gno version for package %s", mpkg.Path) + } } // STEP 2: Parse the mem package to Go AST. - fset, astfs, errs = GoParseMemPackage(mpkg, wtests) + fset, astfs, errs = GoParseMemPackage(mpkg, all) if errs != nil { return nil, nil, nil, fmt.Errorf("go parsing mem package: %v", errs) } @@ -143,8 +151,8 @@ type realm interface{} // shim astfs = append(astfs, astf) // STEP 3: Type-check Gno0.9 AST in Go. - pkg, errs = g.cfg.Check(mpkg.Path, fset, astfs, nil) - return pkg, fset, astfs, errs + pkg, _ = gimp.cfg.Check(mpkg.Path, fset, astfs, nil) + return pkg, fset, astfs, gimp.errors } func deleteOldIdents(idents map[string]func(), astf *ast.File) { diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files/switch13.gno index 64ee14f96e4..66f90153ef3 100644 --- a/gnovm/tests/files/switch13.gno +++ b/gnovm/tests/files/switch13.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/switch13.gno:8:0: i is not a type +// main/files/switch13.gno:9:2: i is not a type // TypeCheckError: // main/files/switch13.gno:9:7: i is not a type From 491167581b64c99f3e3f1e30b2cc85e56969578f Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 10 May 2025 19:50:41 -0700 Subject: [PATCH 09/83] added adr/lint_transpile.md; naming fixes; lint/test works --- gnovm/adr/lint_transpile.md | 31 ++++++ gnovm/cmd/gno/run.go | 6 +- gnovm/cmd/gno/test.go | 84 ++++++++------- gnovm/cmd/gno/tool_lint.go | 147 +++++++++++++------------- gnovm/pkg/gnolang/gotypecheck.go | 29 ++--- gnovm/pkg/gnolang/transpile_gno0p9.go | 79 +++++--------- 6 files changed, 195 insertions(+), 181 deletions(-) create mode 100644 gnovm/adr/lint_transpile.md diff --git a/gnovm/adr/lint_transpile.md b/gnovm/adr/lint_transpile.md new file mode 100644 index 00000000000..3b96b857dbf --- /dev/null +++ b/gnovm/adr/lint_transpile.md @@ -0,0 +1,31 @@ +The steps of Gno 0.0 --> Gno 0.9 transpiling. + 1. `GetMemPackage()`, `ReadMemPackage()`, .... + 2. `ParseGnoMod()`: parse gno.mod (if any) and compare versions. + 3. `GoParse*()`: parse Gno to Go AST with go/parser. + 4. `Prepare*()`: minimal Go AST mutations for Gno VM compat. + 5. `m.PreprocessFiles()`: normal Gno AST preprocessing. + 6. `FindXItems*()`: Gno AST static analaysis to produce xitems. + 7. `Transpile*()` Part 1: re-key xitems by Go Node before step 2 line changes. + 8. `Transpile*()` Part 2: main Go AST mutations for Gno upgrade. + 9. `mpkg.WriteTo()`: write mem package to disk. + +In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: + * Stage 1: (for all dirs) + 1. `gno.ReadMemPackage()` + 2. `gno.TypeCheckMemPackage()` > `ParseGnoMod() + 3. `gno.TypeCheckMemPackage()` > `GoParseMemPackage() + `gno.TypeCheckMemPackage()` > `g.cfg.Check() + 4. `PrepareGno0p9()` + 5. `tm.PreprocessFiles()` + 6. `gno.FindXItemsGno0p9()` + * Stage 2: + 7. `gno.TranspileGno0p9()` Part 1 + 8. `gno.TranspileGno0p9()` Part 2 + * Stage 3: + 9. `mpkg.WriteTo()` + +In gotypecheck.go, TypeCheck*() diverges at step 4 and terminates: + 1. `mpkg` provided as argument + 2. `ParseGnoMod() + 3. `GoParseMemPackage() + 4. `gimp.cfg.Check(): Go type-checker diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index 45b205bee52..9fa5a7ef5a6 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -138,7 +138,7 @@ func execRun(cfg *runCfg, args []string, io commands.IO) error { func parseFiles(fnames []string, stderr io.WriteCloser) ([]*gno.FileNode, error) { files := make([]*gno.FileNode, 0, len(fnames)) - var hasError bool + var didPanic bool for _, fname := range fnames { if s, err := os.Stat(fname); err == nil && s.IsDir() { subFns, err := listNonTestFiles(fname) @@ -157,12 +157,12 @@ func parseFiles(fnames []string, stderr io.WriteCloser) ([]*gno.FileNode, error) return nil, err } - hasError = catchRuntimeError(fname, fname, stderr, func() { + didPanic = catchPanic(fname, fname, stderr, func() { files = append(files, gno.MustReadFile(fname)) }) } - if hasError { + if didPanic { return nil, commands.ExitCodeError(1) } return files, nil diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 41d1558a6f8..b48fdc42b20 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -17,7 +17,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/commands" ) -type testCfg struct { +type testCmd struct { verbose bool failfast bool rootDir string @@ -31,7 +31,7 @@ type testCfg struct { } func newTestCmd(io commands.IO) *commands.Command { - cfg := &testCfg{} + cmd := &testCmd{} return commands.NewCommand( commands.Metadata{ @@ -89,14 +89,14 @@ the execution of the tests. This makes testing faster, but means that the initialization of imported pure packages cannot be checked in filetests. `, }, - cfg, + cmd, func(_ context.Context, args []string) error { - return execTest(cfg, args, io) + return execTest(cmd, args, io) }, ) } -func (c *testCfg) RegisterFlags(fs *flag.FlagSet) { +func (c *testCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar( &c.verbose, "v", @@ -168,15 +168,15 @@ func (c *testCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execTest(cfg *testCfg, args []string, io commands.IO) error { - // Default to current directory if no args provided +func execTest(cmd *testCmd, args []string, io commands.IO) error { + // Show a help message by default. if len(args) == 0 { - args = []string{"."} + return flag.ErrHelp } - // guess opts.RootDir - if cfg.rootDir == "" { - cfg.rootDir = gnoenv.RootDir() + // Guess opts.RootDir. + if cmd.rootDir == "" { + cmd.rootDir = gnoenv.RootDir() } paths, err := targetsFromPatterns(args) @@ -189,10 +189,10 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { return nil } - if cfg.timeout > 0 { + if cmd.timeout > 0 { go func() { - time.Sleep(cfg.timeout) - panic("test timed out after " + cfg.timeout.String()) + time.Sleep(cmd.timeout) + panic("test timed out after " + cmd.timeout.String()) }() } @@ -203,17 +203,17 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { // Set up options to run tests. stdout := goio.Discard - if cfg.verbose { + if cmd.verbose { stdout = io.Out() } - opts := test.NewTestOptions(cfg.rootDir, stdout, io.Err()) - opts.RunFlag = cfg.run - opts.Sync = cfg.updateGoldenTests - opts.Verbose = cfg.verbose - opts.Metrics = cfg.printRuntimeMetrics - opts.Events = cfg.printEvents - opts.Debug = cfg.debug - opts.FailfastFlag = cfg.failfast + opts := test.NewTestOptions(cmd.rootDir, stdout, io.Err()) + opts.RunFlag = cmd.run + opts.Sync = cmd.updateGoldenTests + opts.Verbose = cmd.verbose + opts.Metrics = cmd.printRuntimeMetrics + opts.Events = cmd.printEvents + opts.Debug = cmd.debug + opts.FailfastFlag = cmd.failfast buildErrCount := 0 testErrCount := 0 @@ -231,42 +231,48 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { // Determine gnoPkgPath by reading gno.mod from disk. // TODO: Have ReadMemPackage handle it. modfile, _ := gnomod.ParseDir(pkg.Dir) - gnoPkgPath, ok := determinePkgPath(modfile, pkg.Dir, cfg.rootDir) + gnoPkgPath, ok := determinePkgPath(modfile, pkg.Dir, cmd.rootDir) if !ok { io.ErrPrintfln("--- WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") } // Read MemPackage and lint/pretranspile/format. // (gno.mod will be read again). + var errsLint, errsTest error memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) - var hasError bool startedAt := time.Now() - runtimeError := catchRuntimeError(pkg.Dir, gnoPkgPath, io.Err(), func() { + didPanic := catchPanic(pkg.Dir, gnoPkgPath, io.Err(), func() { if modfile == nil || !modfile.Draft { - foundErr, lintErr := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) - if lintErr != nil { - io.ErrPrintln(lintErr) - hasError = true - } else if foundErr { - hasError = true + _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) + if errs != nil { + errsLint = errs + io.ErrPrintln(errs) } - } else if cfg.verbose { + } else if cmd.verbose { io.ErrPrintfln("%s: module is draft, skipping type check", gnoPkgPath) } - err = test.Test(memPkg, pkg.Dir, opts) + errs := test.Test(memPkg, pkg.Dir, opts) + if errs != nil { + errsTest = errs + io.ErrPrintln(errs) + } }) - hasError = hasError || runtimeError // Print status with duration. duration := time.Since(startedAt) dstr := fmtDuration(duration) - if hasError || err != nil { - if err != nil { - io.ErrPrintfln("%s: test pkg: %v", pkg.Dir, err) + if didPanic || errsLint != nil || errsTest != nil { + if errsLint != nil { + io.ErrPrintfln( + "%s: lint pkg: %v", pkg.Dir, errsLint) + } + if errsTest != nil { + io.ErrPrintfln( + "%s: test pkg: %v", pkg.Dir, errsTest) } io.ErrPrintfln("FAIL %s \t%s", pkg.Dir, dstr) testErrCount++ - if cfg.failfast { + if cmd.failfast { return fail() } } else { diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index ab1aaba6fa6..732410ad82e 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -26,6 +26,11 @@ import ( "go.uber.org/multierr" ) +/* + Linting. + Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). +*/ + type processedPackage struct { mpkg *std.MemPackage fset *gno.FileSet @@ -34,7 +39,7 @@ type processedPackage struct { ftests []*gno.FileSet } -type lintCfg struct { +type lintCmd struct { verbose bool rootDir string // min_confidence: minimum confidence of a problem to print it @@ -42,7 +47,7 @@ type lintCfg struct { } func newLintCmd(io commands.IO) *commands.Command { - cfg := &lintCfg{} + cmd := &lintCmd{} return commands.NewCommand( commands.Metadata{ @@ -50,14 +55,14 @@ func newLintCmd(io commands.IO) *commands.Command { ShortUsage: "lint [flags] [...]", ShortHelp: "runs the linter for the specified packages", }, - cfg, + cmd, func(_ context.Context, args []string) error { - return execLint(cfg, args, io) + return execLint(cmd, args, io) }, ) } -func (c *lintCfg) RegisterFlags(fs *flag.FlagSet) { +func (c *lintCmd) RegisterFlags(fs *flag.FlagSet) { rootdir := gnoenv.RootDir() fs.BoolVar(&c.verbose, "v", false, "verbose output when lintning") @@ -89,17 +94,15 @@ func (i lintIssue) String() string { return fmt.Sprintf("%s: %s (code=%s)", i.Location, i.Msg, i.Code) } -func execLint(cfg *lintCfg, args []string, io commands.IO) error { - if len(args) < 1 { +func execLint(cmd *lintCmd, args []string, io commands.IO) error { + // Show a help message by default. + if len(args) == 0 { return flag.ErrHelp } - var ( - verbose = cfg.verbose - rootDir = cfg.rootDir - ) - if rootDir == "" { - rootDir = gnoenv.RootDir() + // Guess opts.RootDir. + if cmd.rootDir == "" { + cmd.rootDir = gnoenv.RootDir() } dirs, err := gnoPackagesFromArgsRecursively(args) @@ -110,7 +113,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { hasError := false bs, ts := test.StoreWithOptions( - rootDir, goio.Discard, + cmd.rootDir, goio.Discard, test.StoreOptions{PreprocessOnly: true}, ) ppkgs := map[string]processedPackage{} @@ -118,7 +121,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { //---------------------------------------- // STAGE 1: for _, dir := range dirs { - if verbose { + if cmd.verbose { io.ErrPrintln(dir) } @@ -144,7 +147,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { // STEP 1: ReadMemPackage() // Read MemPackage with pkgPath. - pkgPath, _ := determinePkgPath(mod, dir, cfg.rootDir) + pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { io.ErrPrintln(issueFromError( @@ -162,71 +165,71 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } // Handle runtime errors - hasRuntimeErr := catchRuntimeError(dir, pkgPath, io.Err(), func() { + didPanic := catchPanic(dir, pkgPath, io.Err(), func() { // Wrap in cache wrap so execution of the linter // doesn't impact other packages. cw := bs.CacheWrap() gs := ts.BeginTransaction(cw, cw, nil) // These are Go types. - var pkg *token.Package - var fset *token.FileSet - var astfs []*ast.File + var pn *gno.PackageNode + var gopkg *types.Package + var gofset *token.FileSet + var gofs []*ast.File var errs error + if false { + println(gopkg, "is not used") + } // Run type checking if mod == nil || !mod.Draft { // STEP 2: ParseGnoMod() // STEP 3: GoParse*() // - // typeCheckAndPrintErrors(mpkg) --> + // lintTypeCheck(mpkg) --> // TypeCheckMemPackage(mpkg) --> // imp.typeCheckMemPackage(mpkg) // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); - // g.cfg.Check(); + // g.cmd.Check(); // // NOTE: Prepare*() is not called. - pkg, fset, astfs, errs = typeCheckAndPrintErrors(io, dir, mpkg, gs) + gopkg, gofset, gofs, errs = lintTypeCheck(io, dir, mpkg, gs) if errs != nil { io.ErrPrintln(errs) hasError = true - } else if foundErr { - hasError = true } - } else if verbose { + } else if cmd.verbose { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } // STEP 4 & 5: Prepare*() and Preprocess*(). - { - // Construct machine for testing. - tm := test.Machine(gs, goio.Discard, pkgPath, false) - defer tm.Release() - - // Gno parse source fileset and test filesets. - all, fset2, _tests, ftests := sourceAndTestFileset(mpkg) - - // Prepare Go AST for preprocessing. - errs := PrepareGno0p9(fset, astfs) - if errs != nil { - io.ErrPrintln(errs) - hasError = true - } + // Construct machine for testing. + tm := test.Machine(gs, goio.Discard, pkgPath, false) + defer tm.Release() + + // Gno parse source fileset and test filesets. + all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + + // Prepare Go AST for preprocessing. + errs = gno.PrepareGno0p9(gofset, gofs) + if errs != nil { + io.ErrPrintln(errs) + hasError = true + } - // Preprocess fset files (w/ some _test.gno). - pn, _ := tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset2, false, false) - // Preprocess _test files (all _test.gno). - for _, fset3 := range _tests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset3, false, false) - } - // Preprocess _filetest.gno files. - for _, fset3 := range ftests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset3, false, false) - } + // Preprocess fset files (w/ some _test.gno). + pn, _ = tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + // Preprocess _test files (all _test.gno). + for _, fset := range _tests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + } + // Preprocess _filetest.gno files. + for _, fset := range ftests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) } // Record results. @@ -245,10 +248,13 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } } }) - if hasRuntimeErr { + if didPanic { hasError = true } } + if hasError { + return commands.ExitCodeError(1) + } //---------------------------------------- // STAGE 2: Transpile to Gno 0.9 @@ -291,18 +297,18 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { } // Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). -func typeCheckAndPrintErrors( +func lintTypeCheck( io commands.IO, dir string, mpkg *std.MemPackage, testStore gno.Store, ) ( - pkg *token.Package, - fset *token.FileSet, - astfs []*ast.File, + gopkg *types.Package, + gofset *token.FileSet, + gofs []*ast.File, errs error) { - pkg, fset, astfs, errs = gno.TypeCheckMemPackage(mpkg, testStore) + gopkg, gofset, gofs, errs = gno.TypeCheckMemPackage(mpkg, testStore) errors := multierr.Errors(errs) for _, err := range errors { switch err := err.(type) { @@ -344,7 +350,6 @@ func typeCheckAndPrintErrors( } // Gno parses and sorts mpkg files into the following filesets: -// - all: all files // - fset: all normal and _test.go files in package excluding `package xxx_test` // integration *_test.gno files. // - _tests: `package xxx_test` integration *_test.gno files, each in their @@ -384,21 +389,21 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( return } -func guessSourcePath(pkg, source string) string { - if info, err := os.Stat(pkg); !os.IsNotExist(err) && !info.IsDir() { - pkg = filepath.Dir(pkg) +func guessSourcePath(pkgPath, fname string) string { + if info, err := os.Stat(pkgPath); !os.IsNotExist(err) && !info.IsDir() { + pkgPath = filepath.Dir(pkgPath) } - sourceJoin := filepath.Join(pkg, source) - if _, err := os.Stat(sourceJoin); !os.IsNotExist(err) { - return filepath.Clean(sourceJoin) + fnameJoin := filepath.Join(pkgPath, fname) + if _, err := os.Stat(fnameJoin); !os.IsNotExist(err) { + return filepath.Clean(fnameJoin) } - if _, err := os.Stat(source); !os.IsNotExist(err) { - return filepath.Clean(source) + if _, err := os.Stat(fname); !os.IsNotExist(err) { + return filepath.Clean(fname) } - return filepath.Clean(pkg) + return filepath.Clean(pkgPath) } // reParseRecover is a regex designed to parse error details from a string. @@ -408,7 +413,7 @@ func guessSourcePath(pkg, source string) string { // dedicated error type. var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) -func catchRuntimeError(dir, pkgPath string, stderr goio.WriteCloser, action func()) (hasError bool) { +func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (didPanic bool) { defer func() { // Errors catched here mostly come from: // gnovm/pkg/gnolang/preprocess.go @@ -417,7 +422,7 @@ func catchRuntimeError(dir, pkgPath string, stderr goio.WriteCloser, action func return } rdebug.PrintStack() - hasError = true + didPanic = true switch verr := r.(type) { case *gno.PreprocessError: err := verr.Unwrap() diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 062fe7cd7cf..920fd6c7316 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -13,7 +13,10 @@ import ( "go.uber.org/multierr" ) -// Type-checking (using go/types) +/* + Type-checking (using go/types). + Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). +*/ // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. @@ -27,7 +30,7 @@ type MemPackageGetter interface { // The syntax checking is performed entirely using Go's go/types package. // TODO: rename these to GoTypeCheck*, goTypeCheck*... func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( - pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { + pkg *types.Package, gofset *token.FileSet, gofs []*ast.File, errs error) { var gimp *gnoImporter gimp = &gnoImporter{ getter: getter, @@ -43,7 +46,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( all := true // type check all .gno files for mpkg (not for imports). strict := true // check gno.mod exists - pkg, fset, astfs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) + pkg, gofset, gofs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) return } @@ -107,7 +110,7 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. // tests cannot be imported and used anyways. // - strict: If true errors on gno.mod version mismatch. func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, strict bool) ( - pkg *types.Package, fset *token.FileSet, astfs []*ast.File, errs error) { + pkg *types.Package, gofset *token.FileSet, gofs []*ast.File, errs error) { // STEP 1: Check gno.mod version. if strict { @@ -118,7 +121,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, str } // STEP 2: Parse the mem package to Go AST. - fset, astfs, errs = GoParseMemPackage(mpkg, all) + gofset, gofs, errs = GoParseMemPackage(mpkg, all) if errs != nil { return nil, nil, nil, fmt.Errorf("go parsing mem package: %v", errs) } @@ -140,23 +143,23 @@ type realm interface{} // shim const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var astf, err = parser.ParseFile( - fset, + var gof, err = parser.ParseFile( + gofset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) if err != nil { panic("error parsing gotypecheck gnobuiltins.go file") } - astfs = append(astfs, astf) + gofs = append(gofs, gof) // STEP 3: Type-check Gno0.9 AST in Go. - pkg, _ = gimp.cfg.Check(mpkg.Path, fset, astfs, nil) - return pkg, fset, astfs, gimp.errors + pkg, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs, nil) + return pkg, gofset, gofs, gimp.errors } -func deleteOldIdents(idents map[string]func(), astf *ast.File) { - for _, decl := range astf.Decls { +func deleteOldIdents(idents map[string]func(), gof *ast.File) { + for _, decl := range gof.Decls { fd, ok := decl.(*ast.FuncDecl) // ignore methods and init functions //nolint:goconst @@ -173,7 +176,7 @@ func deleteOldIdents(idents map[string]func(), astf *ast.File) { // NOTE: cannot use the index as a file may contain // multiple decls to be removed, so removing one would // make all "later" indexes wrong. - astf.Decls = slices.DeleteFunc(astf.Decls, + gof.Decls = slices.DeleteFunc(gof.Decls, func(d ast.Decl) bool { return decl == d }) } } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index f61638674d3..e90b2414b71 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -18,42 +18,11 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -// ======================================== /* - -The steps of Gno 0.0 --> Gno 0.9 transpiling. - 1. GetMemPackage, ReadMemPackage, .... - 2. ParseGnoMod(): parse gno.mod (if any) and compare versions. - 3. GoParse*(): parse Gno to Go AST with go/parser. - 4. Prepare*(): minimal Go AST mutations for Gno VM compat. - 5. m.PreprocessFiles(): normal Gno AST preprocessing. - 6. FindXItems*(): Gno AST static analaysis to produce xitems. - 7. Transpile*() Part 1: re-key xitems by Go Node before step 2 line changes. - 8. Transpile*() Part 2: main Go AST mutations for Gno upgrade. - 9. mpkg.WriteTo(): write mem package to disk. - -In cmd/gno/tool_lint.go each step is grouped into stages for all dirs: - * Stage 1: (for all dirs) - 1. gno.ReadMemPackage() - 2. gno.TypeCheckMemPackage() > ParseGnoMod() - 3. gno.TypeCheckMemPackage() > GoParseMemPackage() - gno.TypeCheckMemPackage() > g.cfg.Check() - 4. PrepareGno0p9() - 5. tm.PreprocessFiles() - 6. gno.FindXItemsGno0p9() - * Stage 2: - 7. gno.TranspileGno0p9() Part 1 - 8. gno.TranspileGno0p9() Part 2 - * Stage 3: - 9. mpkg.WriteTo() - -In gotypecheck.go, TypeCheck*() diverges at step 4 and terminates: - 1. mpkg provided as argument - 2. ParseGnoMod() - 3. GoParseMemPackage() - 4. g.cfg.Check(): Go type-checker - + Transpiling old Gno code to Gno 0.9. + Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). */ + // ======================================== // Parses the gno.mod file from mpkg. // To generate default ones, use: @@ -89,8 +58,8 @@ func ParseGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, outdated bool) { // - wtests: if true also parses and includes all *_test.gno // and *_filetest.gno files. func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( - fset *token.FileSet, astfs []*ast.File, errs error) { - fset = token.NewFileSet() + gofset *token.FileSet, gofs []*ast.File, errs error) { + gofset = token.NewFileSet() // This map is used to allow for function re-definitions, which are // allowed in Gno (testing context) but not in Go. This map links @@ -116,20 +85,20 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( parser.DeclarationErrors | parser.SkipObjectResolution // fmt.Println("GO/PARSER", mpkg.Path, file.Name) - var astf, err = parser.ParseFile( - fset, path.Join(mpkg.Path, file.Name), + var gof, err = parser.ParseFile( + gofset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) if err != nil { errs = multierr.Append(errs, err) continue } - deleteOldIdents(delFunc, astf) + deleteOldIdents(delFunc, gof) // The *ast.File passed all filters. - astfs = append(astfs, astf) + gofs = append(gofs, gof) } if errs != nil { - return fset, astfs, errs + return gofset, gofs, errs } // END processing all files. return @@ -149,10 +118,10 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( // // Results: // - errs: returned in aggregate as a multierr type. -func PrepareGno0p9(fset *token.FileSet, astfs []*ast.File) (errs error) { - for _, astf := range astfs { +func PrepareGno0p9(gofset *token.FileSet, gofs []*ast.File) (errs error) { + for _, gof := range gofs { // AST transform for Gno 0.9. - err := prepareGno0p9(astf) + err := prepareGno0p9(gof) if err != nil { errs = multierr.Append(errs, err) continue @@ -330,7 +299,7 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) } // Go parse and collect files from mpkg. - fset := token.NewFileSet() + gofset := token.NewFileSet() var errs error for _, file := range mpkg.Files { // Ignore non-gno files. @@ -350,8 +319,8 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var astf, err = parser.ParseFile( - fset, + var gof, err = parser.ParseFile( + gofset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) @@ -360,19 +329,19 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) continue } // Transpile Part 1: re-key xform by ast.Node. - xform2, err := transpileGno0p9_part1(mpkg.Path, fset, file.Name, astf, xform) + xform2, err := transpileGno0p9_part1(mpkg.Path, gofset, file.Name, gof, xform) if err != nil { errs = multierr.Append(errs, err) continue } // Transpile Part 2: main Go AST transform for Gno 0.9. - if err := transpileGno0p9_part2(mpkg.Path, fset, file.Name, astf, xform2); err != nil { + if err := transpileGno0p9_part2(mpkg.Path, gofset, file.Name, gof, xform2); err != nil { errs = multierr.Append(errs, err) continue } // Write transformed AST to Go to mem file. var buf bytes.Buffer - err = gofmt.Node(&buf, fset, astf) + err = gofmt.Node(&buf, gofset, gof) if err != nil { errs = multierr.Append(errs, err) continue @@ -442,7 +411,7 @@ func transpileGno0p9_part1(pkgPath string, fs *token.FileSet, fname string, f *a } // The main Go AST transpiling logic to make Gno code Gno 0.9. -func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[ast.Node]string) (err error) { +func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof *ast.File, xform map[ast.Node]string) (err error) { var lastLine = 0 var didRemoveCrossing = false @@ -454,7 +423,7 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, f *a return fs.Position(pos).Line } - astutil.Apply(f, func(c *astutil.Cursor) bool { + astutil.Apply(gof, func(c *astutil.Cursor) bool { // Handle newlines after crossing if didRemoveCrossing { @@ -519,13 +488,13 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, f *a if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { // Replace expression 'cross(x)' by 'x'. // In Gno 0.9 @cross decorator is used instead. - var a ast.Node + var gon ast.Node if len(n.Args) == 1 { - a = n.Args[0] + gon = n.Args[0] } else { err = errors.New("cross called with invalid parameters") } - c.Replace(a) + c.Replace(gon) return true } } From 56b6cdb387b8ae87257c84a7385ee82c4f520216 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 11 May 2025 15:39:29 -0700 Subject: [PATCH 10/83] ... --- .../dao/v3/memberstore/memberstore_test.gno | 3 +- gno.land/pkg/gnoland/genesis.go | 6 +- gno.land/pkg/sdk/vm/keeper.go | 4 +- gnovm/adr/lint_transpile.md | 6 +- gnovm/cmd/gno/test.go | 2 +- gnovm/cmd/gno/tool_lint.go | 53 +++-- gnovm/pkg/gnofmt/package.go | 18 +- gnovm/pkg/gnolang/gnomod.go | 57 +++++- gnovm/pkg/gnolang/gotypecheck.go | 8 +- gnovm/pkg/gnolang/nodes.go | 25 +-- gnovm/pkg/gnolang/store.go | 31 +-- gnovm/pkg/gnolang/transpile_gno0p9.go | 128 ++++++------ gnovm/pkg/gnolang/validate_mempackage.go | 35 ++++ gnovm/pkg/gnolang/version.go | 7 - gnovm/pkg/gnomod/parse.go | 12 +- gnovm/pkg/test/imports.go | 71 ++++--- tm2/pkg/colors/cmd/modcolor/modcolor.go | 34 ++++ tm2/pkg/colors/colors.go | 4 + tm2/pkg/std/memfile.go | 187 ++++++++++++++---- 19 files changed, 482 insertions(+), 209 deletions(-) create mode 100644 gnovm/pkg/gnolang/validate_mempackage.go create mode 100644 tm2/pkg/colors/cmd/modcolor/modcolor.go diff --git a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore_test.gno b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore_test.gno index e5ba6e9b517..8a16b88cebb 100644 --- a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore_test.gno +++ b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore_test.gno @@ -5,7 +5,6 @@ import ( "strconv" "testing" - "gno.land/p/demo/avl" "gno.land/p/demo/urequire" ) @@ -115,7 +114,7 @@ func TestCreateMembers(t *testing.T) { } func addMembers(ms MembersByTier, c int, tier string) { - mt := avl.NewTree() + // mt := avl.NewTree() XXX ms.SetTier(tier) for i := 0; i < c; i++ { addr := std.Address(strconv.Itoa(i) + tier) diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index 8633a80e999..6c5cc689d85 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -208,8 +208,8 @@ func LoadPackage(pkg gnomod.Pkg, creator bft.Address, fee std.Fee, deposit std.C var tx std.Tx // Open files in directory as MemPackage. - memPkg := gno.MustReadMemPackage(pkg.Dir, pkg.Name) - err := memPkg.Validate() + mpkg := gno.MustReadMemPackage(pkg.Dir, pkg.Name) + err := gno.ValidateMemPackage(mpkg) if err != nil { return tx, fmt.Errorf("invalid package: %w", err) } @@ -219,7 +219,7 @@ func LoadPackage(pkg gnomod.Pkg, creator bft.Address, fee std.Fee, deposit std.C tx.Msgs = []std.Msg{ vmm.MsgAddPackage{ Creator: creator, - Package: memPkg, + Package: mpkg, Deposit: deposit, }, } diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 3f951e739bd..7773702b7c7 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -337,7 +337,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { if creatorAcc == nil { return std.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", creator)) } - if err := msg.Package.Validate(); err != nil { + if err := gno.ValidateMemPackage(msg.Package); err != nil { return ErrInvalidPkgPath(err.Error()) } if !strings.HasPrefix(pkgPath, chainDomain+"/") { @@ -582,7 +582,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { if callerAcc == nil { return "", std.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", caller)) } - if err := msg.Package.Validate(); err != nil { + if err := gno.ValidateMemPackage(msg.Package); err != nil { return "", ErrInvalidPkgPath(err.Error()) } diff --git a/gnovm/adr/lint_transpile.md b/gnovm/adr/lint_transpile.md index 3b96b857dbf..1db5f6f4849 100644 --- a/gnovm/adr/lint_transpile.md +++ b/gnovm/adr/lint_transpile.md @@ -24,8 +24,12 @@ In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: * Stage 3: 9. `mpkg.WriteTo()` -In gotypecheck.go, TypeCheck*() diverges at step 4 and terminates: +In `pkg/gnolang/gotypecheck.go`, `TypeCheck*()` diverges at step 4 and terminates: 1. `mpkg` provided as argument 2. `ParseGnoMod() 3. `GoParseMemPackage() 4. `gimp.cfg.Check(): Go type-checker + +In `pkg/test/imports.go`, `_processMemPackage()` after loading when .PreprocessOnly: + 3. `GoParseMemPackage()` + 4. `PrepareGno0p9()` diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index b48fdc42b20..4dfb01a9091 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -236,7 +236,7 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { io.ErrPrintfln("--- WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") } - // Read MemPackage and lint/pretranspile/format. + // Read MemPackage and lint/typecheck/format. // (gno.mod will be read again). var errsLint, errsTest error memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 732410ad82e..c24caf81de4 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -10,6 +10,7 @@ import ( "go/token" "go/types" goio "io" + "io/fs" "os" "path" "path/filepath" @@ -40,8 +41,9 @@ type processedPackage struct { } type lintCmd struct { - verbose bool - rootDir string + verbose bool + rootDir string + autoGnomod bool // min_confidence: minimum confidence of a problem to print it // (default 0.8) auto-fix: apply suggested fixes automatically. } @@ -67,6 +69,7 @@ func (c *lintCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar(&c.verbose, "v", false, "verbose output when lintning") fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)") + fs.BoolVar(&c.autoGnomod, "auto-gnomod", true, "auto-generate gno.mod file if not already present.") } type lintCode string @@ -118,9 +121,11 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ) ppkgs := map[string]processedPackage{} + fmt.Println("LINT DIRS:", dirs) //---------------------------------------- // STAGE 1: for _, dir := range dirs { + fmt.Println("LINT DIR:", dir) if cmd.verbose { io.ErrPrintln(dir) } @@ -130,9 +135,23 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { dir = filepath.Dir(dir) } - // TODO: This should be handled by ReadMemPackage. + // Read and parse gno.mod directly. fpath := path.Join(dir, "gno.mod") mod, err := gnomod.ParseFilepath(fpath) + if errors.Is(err, fs.ErrNotExist) { + if cmd.autoGnomod { + mod, err = gnomod.ParseBytes("gno.mod", []byte(gno.GnoModDefault)) + if err != nil { + panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) + } + io.ErrPrintfln("auto-generated %q", fpath) + err = mod.WriteFile(fpath) + if err != nil { + panic(fmt.Errorf("unexpected panic writing to %q: %w", fpath, err)) + } + // err == nil. + } + } if err != nil { issue := lintIssue{ Code: lintGnoMod, @@ -192,9 +211,8 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - // - // NOTE: Prepare*() is not called. - gopkg, gofset, gofs, errs = lintTypeCheck(io, dir, mpkg, gs) + gopkg, gofset, gofs, errs = + lintTypeCheck(io, dir, mpkg, gs) if errs != nil { io.ErrPrintln(errs) hasError = true @@ -203,21 +221,24 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } - // STEP 4 & 5: Prepare*() and Preprocess*(). + // STEP 4: Prepare*() // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) defer tm.Release() - // Gno parse source fileset and test filesets. - all, fset, _tests, ftests := sourceAndTestFileset(mpkg) - // Prepare Go AST for preprocessing. - errs = gno.PrepareGno0p9(gofset, gofs) + errs = gno.PrepareGno0p9(gofset, gofs, mpkg) if errs != nil { io.ErrPrintln(errs) hasError = true + return // Prepare must succeed. } + // STEP 5: re-parse + // Gno parse source fileset and test filesets. + all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + + // STEP 6: PreprocessFiles() // Preprocess fset files (w/ some _test.gno). pn, _ = tm.PreprocessFiles( mpkg.Name, mpkg.Path, fset, false, false) @@ -236,9 +257,9 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ppkgs[dir] = processedPackage{ mpkg, fset, pn, _tests, ftests} - // STEP 6: FindXItems(): + // STEP 7: FindXItems(): // FindXItems for all files if outdated. - if mod.Gno.Version == "0.0" { + if mod == nil || mod.Gno == nil || mod.Gno.Version == "0.0" { // Use the preprocessor to collect the // transformations needed to be done. // They are collected in @@ -267,7 +288,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { mpkg, pn := ppkg.mpkg, ppkg.pn xform, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) - // STEP 7 & 8: gno.TranspileGno0p9() Part 1 & 2 + // STEP 8 & 9: gno.TranspileGno0p9() Part 1 & 2 err := gno.TranspileGno0p9(mpkg, dir, xform) if err != nil { return err @@ -286,7 +307,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { panic("where did it go") } - // STEP 9: mpkg.WriteTo(): + // STEP 10: mpkg.WriteTo(): err := ppkg.mpkg.WriteTo(dir) if err != nil { return err @@ -342,7 +363,7 @@ func lintTypeCheck( Location: loc, }) default: - errs = fmt.Errorf("unexpected error type; %T", err) + io.ErrPrintfln("unknown error (%T): %s", err, err.Error()) return } } diff --git a/gnovm/pkg/gnofmt/package.go b/gnovm/pkg/gnofmt/package.go index 579e1d063ca..837d1b76c0e 100644 --- a/gnovm/pkg/gnofmt/package.go +++ b/gnovm/pkg/gnofmt/package.go @@ -95,8 +95,8 @@ func ParsePackage(fset *token.FileSet, root string, dir string) (Package, error) var pkgpath string // Check for a gno.mod, in which case it will define the module path - gnoModPath := filepath.Join(dir, "gno.mod") - data, err := os.ReadFile(gnoModPath) + modpath := filepath.Join(dir, "gno.mod") + data, err := os.ReadFile(modpath) switch { case os.IsNotExist(err): if len(root) > 0 { @@ -106,19 +106,19 @@ func ParsePackage(fset *token.FileSet, root string, dir string) (Package, error) } case err == nil: - gnoMod, err := gnomod.ParseBytes(gnoModPath, data) + mod, err := gnomod.ParseBytes(modpath, data) if err != nil { - return nil, fmt.Errorf("unable to parse gnomod %q: %w", gnoModPath, err) + return nil, fmt.Errorf("unable to parse gnomod %q: %w", modpath, err) } - gnoMod.Sanitize() - if err := gnoMod.Validate(); err != nil { - return nil, fmt.Errorf("unable to validate gnomod %q: %w", gnoModPath, err) + mod.Sanitize() + if err := mod.Validate(); err != nil { + return nil, fmt.Errorf("unable to validate gnomod %q: %w", modpath, err) } - pkgpath = gnoMod.Module.Mod.Path + pkgpath = mod.Module.Mod.Path default: - return nil, fmt.Errorf("unable to read %q: %w", gnoModPath, err) + return nil, fmt.Errorf("unable to read %q: %w", modpath, err) } return &fsPackage{ diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index f2cb3577653..dacdd08e2c4 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -11,6 +11,43 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) +const ( + // gno.mod files assumed in testing/default contexts. + GnoModLatest = `go 0.9` // when gno.mod is missing for stdlibs. + GnoModTesting = `go 0.9` // when gno.mod is missing while testing. + GnoModDefault = `go 0.0` // when gno.mod is missing in general. + GnoVerDefault = `0.0` // when gno version isn't specified. +) + +// ======================================== +// Parses and checks the gno.mod file from mpkg. +// To generate default ones, use: +// gnomod.ParseBytes(GnoModDefault) +// +// Results: +// - mod: the gno.mod file, or nil if not found. +// - err: wrapped error +func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { + if IsStdlib(mpkg.Path) { + // stdlib/extern packages are assumed up to date. + mod, _ = gnomod.ParseBytes("/gno.mod", []byte(GnoModLatest)) + } else if mod, _ = gnomod.ParseMemPackage(mpkg); mod == nil { + // gno.mod doesn't exist. + mod, _ = gnomod.ParseBytes(mpkg.Path+"/gno.mod", []byte(GnoModDefault)) + err = fmt.Errorf("%s/gno.mod: not found", mpkg.Path) + } else if mod.Gno == nil { + // 'gno 0.9' was never specified; just write 0.0. + mod.SetGno(GnoVerDefault) + // err = fmt.Errorf("%s/gno.mod: gno version unspecified", mpkg.Path) + } else if mod.Gno.Version == GnoVersion { + // current version, nothing to do. + } else { + panic("unsupported gno version " + mod.Gno.Version) + } + return +} + +// ======================================== // ReadPkgListFromDir() lists all gno packages in the given dir directory. func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { var pkgs []gnomod.Pkg @@ -22,8 +59,8 @@ func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { if !d.IsDir() { return nil } - gmfPath := filepath.Join(path, "gno.mod") - data, err := os.ReadFile(gmfPath) + modPath := filepath.Join(path, "gno.mod") + data, err := os.ReadFile(modPath) if os.IsNotExist(err) { return nil } @@ -31,16 +68,16 @@ func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { return err } - gmf, err := gnomod.ParseBytes(gmfPath, data) + mod, err := gnomod.ParseBytes(modPath, data) if err != nil { return fmt.Errorf("parse: %w", err) } - gmf.Sanitize() - if err := gmf.Validate(); err != nil { - return fmt.Errorf("failed to validate gno.mod in %s: %w", gmfPath, err) + mod.Sanitize() + if err := mod.Validate(); err != nil { + return fmt.Errorf("failed to validate gno.mod in %s: %w", modPath, err) } - pkg, err := ReadMemPackage(path, gmf.Module.Mod.Path) + pkg, err := ReadMemPackage(path, mod.Module.Mod.Path) if err != nil { // ignore package files on error pkg = &std.MemPackage{} @@ -56,7 +93,7 @@ func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { imports := make([]string, 0, len(importsRaw)) for _, imp := range importsRaw { // remove self and standard libraries from imports - if imp.PkgPath != gmf.Module.Mod.Path && + if imp.PkgPath != mod.Module.Mod.Path && !IsStdlib(imp.PkgPath) { imports = append(imports, imp.PkgPath) } @@ -64,8 +101,8 @@ func ReadPkgListFromDir(dir string) (gnomod.PkgList, error) { pkgs = append(pkgs, gnomod.Pkg{ Dir: path, - Name: gmf.Module.Mod.Path, - Draft: gmf.Draft, + Name: mod.Module.Mod.Path, + Draft: mod.Draft, Imports: imports, }) return nil diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 920fd6c7316..72ab81e5a79 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -114,16 +114,16 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, str // STEP 1: Check gno.mod version. if strict { - _, outdated := ParseGnoMod(mpkg) - if outdated { - return nil, nil, nil, fmt.Errorf("outdated gno version for package %s", mpkg.Path) + _, err := ParseCheckGnoMod(mpkg) + if err != nil { + return nil, nil, nil, fmt.Errorf("gimp parse check gno.mod: %w", err) } } // STEP 2: Parse the mem package to Go AST. gofset, gofs, errs = GoParseMemPackage(mpkg, all) if errs != nil { - return nil, nil, nil, fmt.Errorf("go parsing mem package: %v", errs) + return nil, nil, nil, fmt.Errorf("gimp Go mem package: %w", errs) } // STEP 2: Add .gnobuiltins.go file. diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 9fcca726b22..5b3e9658609 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1263,7 +1263,7 @@ func MustReadMemPackage(dir string, pkgPath string) *std.MemPackage { // XXX TODO pkgPath should instead be derived by inspecting the contents, among them // the gno.mod fule. func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, error) { - memPkg := &std.MemPackage{Path: pkgPath} + mpkg := &std.MemPackage{Path: pkgPath} var pkgName Name for _, fpath := range list { fname := filepath.Base(fpath) @@ -1281,23 +1281,26 @@ func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, err pkgName = pkgName[:len(pkgName)-len("_test")] } } - memPkg.Files = append(memPkg.Files, + mpkg.Files = append(mpkg.Files, &std.MemFile{ Name: fname, Body: string(bz), }) } - memPkg.Name = string(pkgName) + mpkg.Name = string(pkgName) // If no .gno files are present, package simply does not exist. - if !memPkg.IsEmpty() { + if !mpkg.IsEmpty() { if err := validatePkgName(string(pkgName)); err != nil { return nil, err } } - return memPkg, nil + // Sort the files for validation purposes. + mpkg.Sort() + + return mpkg, nil } // MustReadMemPackageFromList is a wrapper around [ReadMemPackageFromList] that panics on error. @@ -1309,15 +1312,15 @@ func MustReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { return pkg } -// ParseMemPackage executes [ParseFile] on each file of the memPkg, excluding +// ParseMemPackage executes [ParseFile] on each file of the mpkg, excluding // test and spurious (non-gno) files. The resulting *FileSet is returned. // -// If one of the files has a different package name than memPkg.Name, +// If one of the files has a different package name than mpkg.Name, // or [ParseFile] returns an error, ParseMemPackage panics. -func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { +func ParseMemPackage(mpkg *std.MemPackage) (fset *FileSet) { fset = &FileSet{} var errs error - for _, mfile := range memPkg.Files { + for _, mfile := range mpkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") || endsWithAny(mfile.Name, []string{"_test.gno", "_filetest.gno"}) || mfile.Name == "gno.mod" { @@ -1328,10 +1331,10 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { errs = multierr.Append(errs, err) continue } - if memPkg.Name != string(n.PkgName) { + if mpkg.Name != string(n.PkgName) { panic(fmt.Sprintf( "expected package name [%s] but got [%s]", - memPkg.Name, n.PkgName)) + mpkg.Name, n.PkgName)) } // add package file. fset.AddFiles(n) diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index e0aea296033..dd50f46753d 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -60,7 +60,7 @@ type Store interface { // Upon restart, all packages will be re-preprocessed; This // loads BlockNodes and Types onto the store for persistence // version 1. - AddMemPackage(memPkg *std.MemPackage) + AddMemPackage(mpkg *std.MemPackage) GetMemPackage(path string) *std.MemPackage GetMemFile(path string, name string) *std.MemFile IterMemPackage() <-chan *std.MemPackage @@ -785,7 +785,7 @@ func (ds *defaultStore) incGetPackageIndexCounter() uint64 { } } -func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { +func (ds *defaultStore) AddMemPackage(mpkg *std.MemPackage) { if bm.OpsEnabled { bm.PauseOpCode() defer bm.ResumeOpCode() @@ -798,14 +798,17 @@ func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { bm.StopStore(size) }() } - memPkg.Validate() // NOTE: duplicate validation. + err := ValidateMemPackage(mpkg) // NOTE: duplicate validation. + if err != nil { + panic(fmt.Errorf("invalid mempackage: %w", err)) + } ctr := ds.incGetPackageIndexCounter() idxkey := []byte(backendPackageIndexKey(ctr)) - bz := amino.MustMarshal(memPkg) + bz := amino.MustMarshal(mpkg) gas := overflow.Mulp(ds.gasConfig.GasAddMemPackage, store.Gas(len(bz))) ds.consumeGas(gas, GasAddMemPackageDesc) - ds.baseStore.Set(idxkey, []byte(memPkg.Path)) - pathkey := []byte(backendPackagePathKey(memPkg.Path)) + ds.baseStore.Set(idxkey, []byte(mpkg.Path)) + pathkey := []byte(backendPackagePathKey(mpkg.Path)) ds.iavlStore.Set(pathkey, bz) size = len(bz) } @@ -848,21 +851,21 @@ func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage gas := overflow.Mulp(ds.gasConfig.GasGetMemPackage, store.Gas(len(bz))) ds.consumeGas(gas, GasGetMemPackageDesc) - var memPkg *std.MemPackage - amino.MustUnmarshal(bz, &memPkg) + var mpkg *std.MemPackage + amino.MustUnmarshal(bz, &mpkg) size = len(bz) - return memPkg + return mpkg } // GetMemFile retrieves the MemFile with the given name, contained in the // MemPackage at the given path. It returns nil if the file or the package // do not exist. func (ds *defaultStore) GetMemFile(path string, name string) *std.MemFile { - memPkg := ds.GetMemPackage(path) - if memPkg == nil { + mpkg := ds.GetMemPackage(path) + if mpkg == nil { return nil } - memFile := memPkg.GetFile(name) + memFile := mpkg.GetFile(name) return memFile } @@ -885,8 +888,8 @@ func (ds *defaultStore) IterMemPackage() <-chan *std.MemPackage { panic(fmt.Sprintf( "missing package index %d", i)) } - memPkg := ds.GetMemPackage(string(path)) - ch <- memPkg + mpkg := ds.GetMemPackage(string(path)) + ch <- mpkg } close(ch) }() diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index e90b2414b71..f0a200e352b 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -9,6 +9,7 @@ import ( "go/parser" "go/token" "path" + "path/filepath" "strings" "go.uber.org/multierr" @@ -21,34 +22,9 @@ import ( /* Transpiling old Gno code to Gno 0.9. Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). -*/ -// ======================================== -// Parses the gno.mod file from mpkg. -// To generate default ones, use: -// `mod, _ = gnomod.ParseBytes(gnomodDefault)` -// -// Results: -// - mod: the gno.mod file, or nil if not found. -// - outdated: true if it should be transpiled to the current version. -func ParseGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, outdated bool) { - if IsStdlib(mpkg.Path) { - // stdlib/extern packages are assumed up to date. - mod, _ = gnomod.ParseBytes("/gno.mod", []byte(gnomodLatest)) - } else if mod, _ = gnomod.ParseMemPackage(mpkg); mod == nil { - // gno.mod doesn't exist. - mod, _ = gnomod.ParseBytes(mpkg.Path+"/gno.mod", []byte(gnomodDefault)) - outdated = true - } else if mod.Gno == nil { - // 'gno 0.9' was never specified, continue - outdated = true - } else if mod.Gno.Version == GnoVersion { - // current version, nothing to do. - } else { - panic("unsupported gno version " + mod.Gno.Version) - } - return -} + ParseCheckGnoMod() defined in pkg/gnolang/gnomod.go. +*/ // ======================================== // Go parse the Gno source in mpkg to Go's *token.FileSet and @@ -108,17 +84,20 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( // Prepare Gno 0.0 for Gno 0.9. // // When Gno syntax breaks in higher versions, existing code must first be -// pre-transcribed such that the Gno preprocessor won't panic. This allows old -// Gno code to be preprocessed and used by the Gno VM for static analysis. -// More transpiling will happen later after the preprocessed Gno AST is scanned -// for mutations on the Go AST which follows. Any changes are applied directly -// on the mem package. +// pre-transcribed such that the Gno preprocessor won't panic. This allows +// old Gno code to be preprocessed and used by the Gno VM for static +// analysis. More transpiling will happen later after the preprocessed Gno +// AST is scanned for mutations on the Go AST which follows. Any changes are +// applied directly on the mempackage. // // * Renames 'realm' to 'realm_' to avoid conflict with new uverse type. // +// Args: +// - mpkg: writes (mutated) AST to mempackage if not nil. +// // Results: -// - errs: returned in aggregate as a multierr type. -func PrepareGno0p9(gofset *token.FileSet, gofs []*ast.File) (errs error) { +// - errs: returned in aggregate as a multierr type. +func PrepareGno0p9(gofset *token.FileSet, gofs []*ast.File, mpkg *std.MemPackage) (errs error) { for _, gof := range gofs { // AST transform for Gno 0.9. err := prepareGno0p9(gof) @@ -127,6 +106,7 @@ func PrepareGno0p9(gofset *token.FileSet, gofs []*ast.File) (errs error) { continue } } + errs = WriteToMemPackage(gofset, gofs, mpkg) return } @@ -276,7 +256,7 @@ func addXItem(n Node, t string, p string, f string, l int, c int) { } key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) x[key] = t - fmt.Printf("Gno 0.9 xpile +%s:%s\n", t, key) + fmt.Printf("Gno 0.9 transpile +%s:%s\n", t, key) } // ======================================== @@ -292,25 +272,25 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) // Return if gno.mod is current. var mod *gnomod.File - var outdated bool = false - mod, outdated = ParseGnoMod(mpkg) - if !outdated { + var err error + mod, err = ParseCheckGnoMod(mpkg) + if err == nil { return nil // already up-to-date. } // Go parse and collect files from mpkg. gofset := token.NewFileSet() var errs error - for _, file := range mpkg.Files { + for _, mfile := range mpkg.Files { // Ignore non-gno files. - if !strings.HasSuffix(file.Name, ".gno") { + if !strings.HasSuffix(mfile.Name, ".gno") { continue } /* // Ignore _test/_filetest.gno files unless testing. if !testing { - if strings.HasSuffix(file.Name, "_test.gno") || - strings.HasSuffix(file.Name, "_filetest.gno") { + if strings.HasSuffix(mfile.Name, "_test.gno") || + strings.HasSuffix(mfile.Name, "_filetest.gno") { continue } } @@ -321,45 +301,41 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) parser.SkipObjectResolution var gof, err = parser.ParseFile( gofset, - path.Join(mpkg.Path, file.Name), - file.Body, + path.Join(mpkg.Path, mfile.Name), + mfile.Body, parseOpts) if err != nil { errs = multierr.Append(errs, err) continue } // Transpile Part 1: re-key xform by ast.Node. - xform2, err := transpileGno0p9_part1(mpkg.Path, gofset, file.Name, gof, xform) + xform2, err := transpileGno0p9_part1(mpkg.Path, gofset, mfile.Name, gof, xform) if err != nil { errs = multierr.Append(errs, err) continue } // Transpile Part 2: main Go AST transform for Gno 0.9. - if err := transpileGno0p9_part2(mpkg.Path, gofset, file.Name, gof, xform2); err != nil { + if err := transpileGno0p9_part2(mpkg.Path, gofset, mfile.Name, gof, xform2); err != nil { errs = multierr.Append(errs, err) continue } - // Write transformed AST to Go to mem file. - var buf bytes.Buffer - err = gofmt.Node(&buf, gofset, gof) - if err != nil { + // Write transformed Go AST to memfile. + if err := WriteToMemFile(gofset, gof, mfile); err != nil { errs = multierr.Append(errs, err) continue } - file.Body = buf.String() } if errs != nil { return errs } - // END processing all files. + // END processing all memfiles. - // Write version to mod and to mem file named "gno.mod". + // Write version to mod and to memfile named "gno.mod". mod.SetGno(GnoVersion) - mf := mpkg.GetFile("gno.mod") - mf.Body = mod.WriteString() + mpkg.SetFile("gno.mod", mod.WriteString()) - // Write mem package to dir. - err := mpkg.WriteTo(dir) + // Write mempackage to dir. + err = mpkg.WriteTo(dir) return err } @@ -502,3 +478,41 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof }, nil) return err } + +// ======================================== +// WriteToMemPackage writes Go AST to a mempackage +// This is useful for preparing prior version code for the preprocessor. +func WriteToMemPackage(gofset *token.FileSet, gofs []*ast.File, mpkg *std.MemPackage) error { + for _, gof := range gofs { + fpath := gofset.File(gof.Pos()).Name() + _, fname := filepath.Split(fpath) + mfile := mpkg.GetFile(fname) + if mfile == nil { + if strings.HasPrefix(fname, ".") { + // Hidden files like .gnobuiltins.gno that + // start with a dot should not get written to + // the mempackage. + continue + } else { + return fmt.Errorf("missing memfile %q", mfile) + } + } + err := WriteToMemFile(gofset, gof, mfile) + if err != nil { + return fmt.Errorf("writing to mempackage %q: %w", + mpkg.Path, err) + } + } + return nil +} + +func WriteToMemFile(gofset *token.FileSet, gof *ast.File, mfile *std.MemFile) error { + var buf bytes.Buffer + err := gofmt.Node(&buf, gofset, gof) + if err != nil { + return fmt.Errorf("writing to memfile %q: %w", + mfile.Name, err) + } + mfile.Body = buf.String() + return nil +} diff --git a/gnovm/pkg/gnolang/validate_mempackage.go b/gnovm/pkg/gnolang/validate_mempackage.go new file mode 100644 index 00000000000..e156f540f31 --- /dev/null +++ b/gnovm/pkg/gnolang/validate_mempackage.go @@ -0,0 +1,35 @@ +package gnolang + +import ( + "fmt" + "regexp" + + "github.com/gnolang/gno/tm2/pkg/std" +) + +var ( + // NOTE: These are further restrictions upon the validation that already happens by std.MemPackage.Validate(). + // sub.domain.com/a/any + // sub.domain.com/b/single + // sub.domain.com/c/letter + // sub.domain.com/d/works + // sub.domain.com/r/realm + // sub.domain.com/r/realm/path + // sub.domain.com/p/package/path + // See also tm2/pkg/std/memfile.go. + reGnoPkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:[a-z])(?:\/_?[a-z][a-z0-9_]*)+$`) + reGnoPkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) +) + +func ValidateMemPackage(mpkg *std.MemPackage) error { + err := mpkg.ValidateBasic() + if err != nil { + return err + } + if true && // none of these match... + !reGnoPkgPathURL.MatchString(mpkg.Path) && + !reGnoPkgPathStd.MatchString(mpkg.Path) { + return fmt.Errorf("invalid package/realm path %q", mpkg.Path) + } + return nil +} diff --git a/gnovm/pkg/gnolang/version.go b/gnovm/pkg/gnolang/version.go index 91f36b080d3..0a3144b21a4 100644 --- a/gnovm/pkg/gnolang/version.go +++ b/gnovm/pkg/gnolang/version.go @@ -3,10 +3,3 @@ package gnolang const ( GnoVersion = "0.9" // Gno 0.9 is the current version. ) - -const ( - // gno.mod files assumed in testing/default contexts. - gnomodLatest = `go 0.9` // when gno.mod is missing for stdlibs. - gnomodTesting = `go 0.9` // when gno.mod is missing while testing. - gnomodDefault = `go 0.0` // when gno.mod is missing in general. -) diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index 0b68a4f5a70..08cf6d260ea 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -44,7 +44,7 @@ func ParseDir(dir string) (*File, error) { return gm, nil } -// tries to parse gno mod file given the file path, using ParseBytes and Validate. +// Tries to parse gno mod file given the file path, using ParseBytes and Validate. func ParseFilepath(fpath string) (*File, error) { file, err := os.Stat(fpath) if err != nil { @@ -130,20 +130,20 @@ func ParseMemPackage(mpkg *std.MemPackage) (*File, error) { mpkg.Path, mpkg.Name, ) } - gmf, err := ParseBytes(mf.Name, []byte(mf.Body)) + mod, err := ParseBytes(mf.Name, []byte(mf.Body)) if err != nil { return nil, err } - return gmf, nil + return mod, nil } // Must parse gno.mod from MemPackage. func MustParseMemPackage(mpkg *std.MemPackage) *File { - gmf, err := ParseMemPackage(mpkg) + mod, err := ParseMemPackage(mpkg) if err != nil { - panic(err) + panic(fmt.Errorf("parsing mempackage %w", err)) } - return gmf + return mod } var reGnoVersion = regexp.MustCompile(`^([0-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index e5d584fee55..7509e7eb781 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -43,6 +43,7 @@ func Store( return StoreWithOptions(rootDir, output, StoreOptions{}) } +// ======================================== // StoreWithOptions is a variant of [Store] which additionally accepts a // [StoreOptions] argument. func StoreWithOptions( @@ -53,22 +54,41 @@ func StoreWithOptions( baseStore storetypes.CommitStore, resStore gno.Store, ) { - processMemPackage := func(m *gno.Machine, memPkg *std.MemPackage, save bool) (*gno.PackageNode, *gno.PackageValue) { - return m.RunMemPackage(memPkg, save) - } - if opts.PreprocessOnly { - processMemPackage = func(m *gno.Machine, memPkg *std.MemPackage, save bool) (*gno.PackageNode, *gno.PackageValue) { - m.Store.AddMemPackage(memPkg) - /* NOTE: Don't pre-transpile here, just gno lint the test files and fix them. - _, _, err := gno.PretranspileToGno0p9(memPkg, false) // no need for _test.gno or _filetest.gno files. - if err != nil { - panic("error pretranspiling to Gno 0.9: " + err.Error()) + //---------------------------------------- + // process the mempackage after gno.MustReadMemPackage(). + // * m.PreprocessFiles() if opts.PreprocessOnly. + // * m.RunMemPackage() otherwise. + var _processMemPackage = func( + m *gno.Machine, mpkg *std.MemPackage, save bool) ( + pn *gno.PackageNode, pv *gno.PackageValue) { + if opts.PreprocessOnly { + fmt.Println("WILL PROCESS", mpkg.Path) + // In order to translate into a newer Gno version with + // the preprocessor make a slight modifications to the + // AST. This needs to happen even for imports, because + // the preprocessor requries imports also preprocessed. + const wtests = false // Tests don't matter for imports. + gofset, gofs, errs := gno.GoParseMemPackage(mpkg, wtests) + if errs != nil { + panic(fmt.Errorf("test store parsing: %w", errs)) + } + errs = gno.PrepareGno0p9(gofset, gofs, mpkg) + if errs != nil { + panic(fmt.Errorf("test store preparing AST: %w", errs)) } - */ - return m.PreprocessFiles(memPkg.Name, memPkg.Path, gno.ParseMemPackage(memPkg), save, false) + m.Store.AddMemPackage(mpkg) + return m.PreprocessFiles( + mpkg.Name, mpkg.Path, + gno.ParseMemPackage(mpkg), + save, false) + } else { + return m.RunMemPackage(mpkg, save) } } - getPackage := func(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { + + //---------------------------------------- + // Main entrypoint for new test imports. + var getPackage = func(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { if pkgPath == "" { panic(fmt.Sprintf("invalid zero package path in testStore().pkgGetter")) } @@ -78,7 +98,7 @@ func StoreWithOptions( const testPath = "github.com/gnolang/gno/_test/" if strings.HasPrefix(pkgPath, testPath) { baseDir := filepath.Join(rootDir, "gnovm", "tests", "files", "extern", pkgPath[len(testPath):]) - memPkg := gno.MustReadMemPackage(baseDir, pkgPath) + mpkg := gno.MustReadMemPackage(baseDir, pkgPath) send := std.Coins{} ctx := Context("", pkgPath, send) m2 := gno.NewMachineWithOptions(gno.MachineOptions{ @@ -88,7 +108,7 @@ func StoreWithOptions( Context: ctx, ReviveEnabled: true, }) - return processMemPackage(m2, memPkg, true) + return _processMemPackage(m2, mpkg, true) } } @@ -101,8 +121,8 @@ func StoreWithOptions( // if examples package... examplePath := filepath.Join(rootDir, "examples", pkgPath) if osm.DirExists(examplePath) { - memPkg := gno.MustReadMemPackage(examplePath, pkgPath) - if memPkg.IsEmpty() { + mpkg := gno.MustReadMemPackage(examplePath, pkgPath) + if mpkg.IsEmpty() { panic(fmt.Sprintf("found an empty package %q", pkgPath)) } @@ -115,10 +135,13 @@ func StoreWithOptions( Context: ctx, ReviveEnabled: true, }) - return processMemPackage(m2, memPkg, true) + return _processMemPackage(m2, mpkg, true) } return nil, nil } + + //---------------------------------------- + // Construct new stores db := memdb.NewMemDB() baseStore = dbadapter.StoreConstructor(db, storetypes.StoreOptions{}) // Make a new store. @@ -157,7 +180,7 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer, prep return nil, nil } - memPkg := gno.MustReadMemPackageFromList(files, pkgPath) + mpkg := gno.MustReadMemPackageFromList(files, pkgPath) m2 := gno.NewMachineWithOptions(gno.MachineOptions{ // NOTE: see also pkgs/sdk/vm/builtins.go // Needs PkgPath != its name because TestStore.getPackage is the package @@ -168,11 +191,11 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer, prep ReviveEnabled: true, }) if preprocessOnly { - m2.Store.AddMemPackage(memPkg) - return m2.PreprocessFiles(memPkg.Name, memPkg.Path, gno.ParseMemPackage(memPkg), true, true) + m2.Store.AddMemPackage(mpkg) + return m2.PreprocessFiles(mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), true, true) } // TODO: make this work when using gno lint. - return m2.RunMemPackageWithOverrides(memPkg, true) + return m2.RunMemPackageWithOverrides(mpkg, true) } type stackWrappedError struct { @@ -190,7 +213,7 @@ func (e *stackWrappedError) String() string { // from the store. This is mostly useful for "eager import loading", whereby all // imports are pre-loaded in a permanent store, so that the tests can use // ephemeral transaction stores. -func LoadImports(store gno.Store, memPkg *std.MemPackage) (err error) { +func LoadImports(store gno.Store, mpkg *std.MemPackage) (err error) { defer func() { // This is slightly different from other similar error handling; we do not have a // machine to work with, as this comes from an import; so we need @@ -212,7 +235,7 @@ func LoadImports(store gno.Store, memPkg *std.MemPackage) (err error) { }() fset := token.NewFileSet() - importsMap, err := packages.Imports(memPkg, fset) + importsMap, err := packages.Imports(mpkg, fset) if err != nil { return err } diff --git a/tm2/pkg/colors/cmd/modcolor/modcolor.go b/tm2/pkg/colors/cmd/modcolor/modcolor.go new file mode 100644 index 00000000000..6b6728b3d2c --- /dev/null +++ b/tm2/pkg/colors/cmd/modcolor/modcolor.go @@ -0,0 +1,34 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" + + "github.com/gnolang/gno/tm2/pkg/colors" +) + +var order = []colors.Color{colors.None, colors.Gray, colors.Cyan, colors.Blue, colors.Green, colors.Yellow, colors.Red, colors.Magenta} +var modPtr = flag.Int("mod", 2, "modulo number of lines; maximum 8") + +func main() { + flag.Parse() + if *modPtr < 2 || 8 < *modPtr { + panic("--mod must be between 2 and 8") + } + + var mod = *modPtr + var rin = bufio.NewReader(os.Stdin) + for i := 0; ; i++ { + line, err := rin.ReadString('\n') + if err == io.EOF { + return + } else if err != nil { + panic(err) + } + color := order[i%mod] + fmt.Println(color(line[:len(line)-1])) + } +} diff --git a/tm2/pkg/colors/colors.go b/tm2/pkg/colors/colors.go index 4cecf38640a..05a74f5b44e 100644 --- a/tm2/pkg/colors/colors.go +++ b/tm2/pkg/colors/colors.go @@ -68,6 +68,10 @@ func Red(args ...any) string { return treatAll(ANSIFgRed, args...) } +func RedBg(args ...any) string { + return treatAll(ANSIBgRed, args...) +} + func Green(args ...any) string { return treatAll(ANSIFgGreen, args...) } diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 9183877733c..976c9c208ab 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -5,21 +5,65 @@ import ( "io/ioutil" "path/filepath" "regexp" + "slices" "sort" "strings" ) +// XXX rename to mempackage.go + +const fileNameLimit = 256 +const pkgNameLimit = 256 +const pkgPathLimit = 256 + +var ( + // See also gnovm/pkg/gnolang/validate_mempackage.go. + reFileName = regexp.MustCompile(`^(([a-z0-9_]+|[A-Z0-9_]+)\.[a-z0-9_]{1,7}|LICENSE|README)$`) + rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) + rePkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:p|r)(?:\/_?[a-z]+[a-z0-9_]*)+$`) + rePkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) +) + +//---------------------------------------- +// MemPackage + // A MemFile is the simplest representation of a "file". // -// Notice it doesn't have owners or timestamps. Keep this as is for -// portability. Not even date created, ownership, or other attributes. Just a -// name, and a body. This keeps things portable, easy to hash (otherwise need -// to manage e.g. the encoding and portability of timestamps). +// File Name must contain a single dot and extension. +// File Name may be ALLCAPS.xxx or lowercase.xxx; extensions lowercase. +// e.g. OK: README.md, readme.md, readme.txt, READ.me +// e.g. NOT OK: Readme.md, readme.MD, README, .readme +// File Body can be any string. +// +// NOTE: It doesn't have owners or timestamps. Keep this as is for portability. +// Not even date created, ownership, or other attributes. Just a name, and a +// body. This keeps things portable, easy to hash (otherwise need to manage +// e.g. the encoding and portability of timestamps). type MemFile struct { Name string `json:"name" yaml:"name"` Body string `json:"body" yaml:"body"` } +func (mfile *MemFile) ValidateBasic() error { + if len(mfile.Name) > fileNameLimit { + return fmt.Errorf("name length %d exceeds limit %d", len(mfile.Name), fileNameLimit) + } + if !reFileName.MatchString(mfile.Name) { + return fmt.Errorf("invalid file name %q", mfile.Name) + } + return nil +} + +// Print file to stdout. +func (mfile *MemFile) Print() error { + fmt.Printf("MemFile[%q]:\n", mfile.Name) + fmt.Println(mfile.Body) + return nil +} + +//---------------------------------------- +// MemPackage + // MemPackage represents the information and files of a package which will be // stored in memory. It will generally be initialized by package gnolang's // ReadMemPackage. @@ -32,34 +76,29 @@ type MemPackage struct { Files []*MemFile `json:"files" yaml:"files"` // plain file system files. } -const pathLengthLimit = 256 - -var ( - rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) - rePkgOrRlmPath = regexp.MustCompile(`^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}\/(?:p|r)(?:\/_?[a-z]+[a-z0-9_]*)+$`) - reFileName = regexp.MustCompile(`^([a-zA-Z0-9_]*\.[a-z0-9_\.]*|LICENSE|README)$`) -) - -// path must not contain any dots after the first domain component. -// file names must contain dots. -// NOTE: this is to prevent conflicts with nested paths. -func (mpkg *MemPackage) Validate() error { +// Package Name must be lower_case, can have digits & underscores. +// Package Path must be "a.valid.url/path" or a "simple/path". +// An empty MemPackager is invalid. +func (mpkg *MemPackage) ValidateBasic() error { // add assertion that MemPkg contains at least 1 file if len(mpkg.Files) <= 0 { return fmt.Errorf("no files found within package %q", mpkg.Name) } - - if len(mpkg.Path) > pathLengthLimit { - return fmt.Errorf("path length %d exceeds limit %d", len(mpkg.Path), pathLengthLimit) + if len(mpkg.Name) > pkgNameLimit { + return fmt.Errorf("name length %d exceeds limit %d", len(mpkg.Name), pkgNameLimit) + } + if len(mpkg.Path) > pkgPathLimit { + return fmt.Errorf("path length %d exceeds limit %d", len(mpkg.Path), pkgPathLimit) } - if !rePkgName.MatchString(mpkg.Name) { - return fmt.Errorf("invalid package name %q, failed to match %q", mpkg.Name, rePkgName) + return fmt.Errorf("invalid package name %q", mpkg.Name) } - - if !rePkgOrRlmPath.MatchString(mpkg.Path) { - return fmt.Errorf("invalid package/realm path %q, failed to match %q", mpkg.Path, rePkgOrRlmPath) + if true && // none of these match... + !rePkgPathURL.MatchString(mpkg.Path) && + !rePkgPathStd.MatchString(mpkg.Path) { + return fmt.Errorf("invalid package path %q", mpkg.Path) } + // enforce sorting files based on Go conventions for predictability sorted := sort.SliceIsSorted( mpkg.Files, @@ -68,41 +107,96 @@ func (mpkg *MemPackage) Validate() error { }, ) if !sorted { + for i := 0; i < len(mpkg.Files); i++ { + fmt.Println(">>>", i, mpkg.Files[i].Name) + } return fmt.Errorf("mempackage %q has unsorted files", mpkg.Path) } - var prev string - for i, file := range mpkg.Files { - if !reFileName.MatchString(file.Name) { - return fmt.Errorf("invalid file name %q, failed to match %q", file.Name, reFileName) + // unique filenames + if err := mpkg.Uniq(); err != nil { + return err + } + + // validate files + for _, mfile := range mpkg.Files { + if err := mfile.ValidateBasic(); err != nil { + return fmt.Errorf("invalid file in package: %w", err) } - if i > 0 && prev == file.Name { - return fmt.Errorf("duplicate file name %q", file.Name) + if !reFileName.MatchString(mfile.Name) { + return fmt.Errorf("invalid file name %q, failed to match %q", mfile.Name, reFileName) } - prev = file.Name } + return nil +} +// Returns an error if lowercase(file.Name) are not unique. +func (mpkg *MemPackage) Uniq() error { + var uniq = make(map[string]struct{}, len(mpkg.Files)) + for _, mfile := range mpkg.Files { + lname := strings.ToLower(mfile.Name) + if _, exists := uniq[lname]; exists { + return fmt.Errorf("duplicate file name %q", lname) + } + uniq[lname] = struct{}{} + } return nil } +// Sort files; a MemPackage with unordered files is in valid. +func (mpkg *MemPackage) Sort() { + slices.SortFunc(mpkg.Files, func(a, b *MemFile) int { + return strings.Compare(a.Name, b.Name) + }) +} + +// Return the named file or none if it doesn't exist. func (mpkg *MemPackage) GetFile(name string) *MemFile { - for _, memFile := range mpkg.Files { - if memFile.Name == name { - return memFile + for _, mfile := range mpkg.Files { + if mfile.Name == name { + return mfile } } return nil } +func (mpkg *MemPackage) appendFile(mfile *MemFile) { + mpkg.Files = append(mpkg.Files, mfile) +} + +// Creates a new MemFile and appends without validation. +func (mpkg *MemPackage) NewFile(name string, body string) (mfile *MemFile) { + mfile = &MemFile{ + Name: name, + Body: body, + } + mpkg.appendFile(mfile) + return +} + +// Writes to existing file or creates a new one. +func (mpkg *MemPackage) SetFile(name string, body string) *MemFile { + for _, mfile := range mpkg.Files { + if mfile.Name == name { + mfile.Body = body + return mfile + } + } + return mpkg.NewFile(name, body) +} + +// Returns true if zero. +// XXX Reconsider renaming all IsEmpty() to IsZero(), each carefully. func (mpkg *MemPackage) IsEmpty() bool { return mpkg.Name == "" || len(mpkg.Files) == 0 } -func (mpkg *MemPackage) WriteTo(dirPath string) error { - for _, file := range mpkg.Files { - fmt.Printf("MemPackage.WriteTo(%s) (%d) bytes written\n", file.Name, len(file.Body)) - fpath := filepath.Join(dirPath, file.Name) - err := ioutil.WriteFile(fpath, []byte(file.Body), 0644) +// Write all files into dir. +func (mpkg *MemPackage) WriteTo(dir string) error { + for _, mfile := range mpkg.Files { + fmt.Printf("MemPackage.WriteTo(%s) (%d) bytes written\n", mfile.Name, len(mfile.Body)) + fpath := filepath.Join(dir, mfile.Name) + err := ioutil.WriteFile(fpath, []byte(mfile.Body), 0644) if err != nil { return err } @@ -110,11 +204,20 @@ func (mpkg *MemPackage) WriteTo(dirPath string) error { return nil } +// Print all files to stdout. +func (mpkg *MemPackage) Print() error { + fmt.Printf("MemPackage[%q %s]:\n", mpkg.Path, mpkg.Name) + for _, mfile := range mpkg.Files { + mfile.Print() + } + return nil +} + const licenseName = "LICENSE" -// Splits a path into the dirpath and filename. -func SplitFilepath(filepath string) (dirpath string, filename string) { - parts := strings.Split(filepath, "/") +// Splits a path into the dir and filename. +func SplitFilepath(fpath string) (dir string, filename string) { + parts := strings.Split(fpath, "/") if len(parts) == 1 { return parts[0], "" } From cbba4893cc64ffdf890896bcf6cfb2c6f814e07e Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 11 May 2025 20:03:01 -0700 Subject: [PATCH 11/83] xpiling works ish --- gnovm/adr/lint_transpile.md | 22 ++- gnovm/cmd/gno/tool_lint.go | 33 ++-- gnovm/pkg/gnolang/transpile_gno0p9.go | 272 +++++++++++++++++--------- gnovm/pkg/gnomod/file.go | 8 + gnovm/pkg/test/imports.go | 1 - tm2/pkg/std/memfile.go | 11 +- 6 files changed, 236 insertions(+), 111 deletions(-) diff --git a/gnovm/adr/lint_transpile.md b/gnovm/adr/lint_transpile.md index 1db5f6f4849..51260eab2e5 100644 --- a/gnovm/adr/lint_transpile.md +++ b/gnovm/adr/lint_transpile.md @@ -3,11 +3,12 @@ The steps of Gno 0.0 --> Gno 0.9 transpiling. 2. `ParseGnoMod()`: parse gno.mod (if any) and compare versions. 3. `GoParse*()`: parse Gno to Go AST with go/parser. 4. `Prepare*()`: minimal Go AST mutations for Gno VM compat. - 5. `m.PreprocessFiles()`: normal Gno AST preprocessing. - 6. `FindXItems*()`: Gno AST static analaysis to produce xitems. - 7. `Transpile*()` Part 1: re-key xitems by Go Node before step 2 line changes. - 8. `Transpile*()` Part 2: main Go AST mutations for Gno upgrade. - 9. `mpkg.WriteTo()`: write mem package to disk. + 5. `gno.MustParseFile()`: re-parse prepared AST + 6. `m.PreprocessFiles()`: normal Gno AST preprocessing. + 7. `FindXforms*()`: Gno AST static analaysis to produce xitems. + 8. `Transpile*()` Part 1: re-key xitems by Go Node before step 2 line changes. + 9. `Transpile*()` Part 2: main Go AST mutations for Gno upgrade. + 10. `mpkg.WriteTo()`: write mem package to disk. In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: * Stage 1: (for all dirs) @@ -16,13 +17,14 @@ In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: 3. `gno.TypeCheckMemPackage()` > `GoParseMemPackage() `gno.TypeCheckMemPackage()` > `g.cfg.Check() 4. `PrepareGno0p9()` - 5. `tm.PreprocessFiles()` - 6. `gno.FindXItemsGno0p9()` + 5. `sourceAndTestFileset()` > `gno.MustParseFile()` + 6. `tm.PreprocessFiles()` + 7. `gno.FindXformsGno0p9()` * Stage 2: - 7. `gno.TranspileGno0p9()` Part 1 - 8. `gno.TranspileGno0p9()` Part 2 + 8. `gno.TranspileGno0p9()` Part 1 + 9. `gno.TranspileGno0p9()` Part 2 * Stage 3: - 9. `mpkg.WriteTo()` + 10. `mpkg.WriteTo()` In `pkg/gnolang/gotypecheck.go`, `TypeCheck*()` diverges at step 4 and terminates: 1. `mpkg` provided as argument diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index c24caf81de4..b16260cfada 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -121,11 +121,11 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ) ppkgs := map[string]processedPackage{} - fmt.Println("LINT DIRS:", dirs) + fmt.Println("linting directories...", dirs) //---------------------------------------- // STAGE 1: for _, dir := range dirs { - fmt.Println("LINT DIR:", dir) + fmt.Printf("linting %q\n", dir) if cmd.verbose { io.ErrPrintln(dir) } @@ -161,7 +161,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } io.ErrPrintln(issue) hasError = true - continue + return commands.ExitCodeError(1) } // STEP 1: ReadMemPackage() @@ -201,7 +201,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Run type checking - if mod == nil || !mod.Draft { + if !mod.Draft { // STEP 2: ParseGnoMod() // STEP 3: GoParse*() // @@ -221,6 +221,11 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } + // If gno version is already 0.9, skip. + if mod.GetGno() == "0.9" { // XXX + return + } + // STEP 4: Prepare*() // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) @@ -257,15 +262,15 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ppkgs[dir] = processedPackage{ mpkg, fset, pn, _tests, ftests} - // STEP 7: FindXItems(): - // FindXItems for all files if outdated. - if mod == nil || mod.Gno == nil || mod.Gno.Version == "0.0" { + // STEP 7: FindXforms(): + // FindXforms for all files if outdated. + if mod.GetGno() == "0.0" { // Use the preprocessor to collect the // transformations needed to be done. // They are collected in - // pn.GetAttribute("XREALMITEM") + // pn.GetAttribute("XREALMFORM") for _, fn := range all.Files { - gno.FindXItemsGno0p9(gs, pn, fn) + gno.FindXformsGno0p9(gs, pn, fn) } } }) @@ -286,10 +291,16 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { panic("where did it go") } mpkg, pn := ppkg.mpkg, ppkg.pn - xform, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XITEMS).(map[string]string) + + // If gno version is already 0.9, skip. + mod, err := gno.ParseCheckGnoMod(mpkg) + if mod.GetGno() == "0.9" { // XXX + continue + } // STEP 8 & 9: gno.TranspileGno0p9() Part 1 & 2 - err := gno.TranspileGno0p9(mpkg, dir, xform) + xforms1, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XFORMS).(map[string]struct{}) + err = gno.TranspileGno0p9(mpkg, dir, xforms1) if err != nil { return err } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index f0a200e352b..25133702ab7 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -60,7 +60,6 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - // fmt.Println("GO/PARSER", mpkg.Path, file.Name) var gof, err = parser.ParseFile( gofset, path.Join(mpkg.Path, file.Name), file.Body, @@ -114,11 +113,11 @@ func PrepareGno0p9(gofset *token.FileSet, gofs []*ast.File, mpkg *std.MemPackage // - Renames 'realm' to '_realm' to avoid conflict with new builtin "realm". func prepareGno0p9(f *ast.File) (err error) { astutil.Apply(f, func(c *astutil.Cursor) bool { - switch n := c.Node().(type) { + switch gon := c.Node().(type) { case *ast.Ident: - if n.Name == "realm" { + if gon.Name == "realm" { // XXX: optimistic. - n.Name = "_realm" + gon.Name = "_realm" } } return true @@ -127,17 +126,17 @@ func prepareGno0p9(f *ast.File) (err error) { } //======================================== -// Find XItems for Gno 0.0 --> Gno 0.9. +// Find Xforms for Gno 0.0 --> Gno 0.9. -// XItem represents a single needed transform. -type XItem struct { +// Xform represents a single needed transform. +type Xform struct { Type string Location } -// Finds XItems for Gno 0.9 from the Gno AST and stores them pn -// ATTR_GNO0P9_XITEMS. -func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { +// Finds Xforms for Gno 0.9 from the Gno AST and stores them pn +// ATTR_GNO0P9_XFORMS. +func FindXformsGno0p9(store Store, pn *PackageNode, bn BlockNode) { // create stack of BlockNodes. var stack []BlockNode = make([]BlockNode, 0, 32) var last BlockNode = pn @@ -182,20 +181,20 @@ func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { panic("cross(fn) must be followed by a call") } loc := last.GetLocation() - addXItem(pn, "add nilrealm", loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + addXform1(pn, XTYPE_ADD_NILREALM, loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { if !IsRealmPath(pn.PkgPath) { panic("crossing() is only allowed in realm packages") } // Add `cur realm` as first argument to func decl. loc := last.GetLocation() - addXItem(pn, "add curfunc", loc.PkgPath, loc.File, loc.Line, loc.Column) + addXform1(pn, XTYPE_ADD_CURFUNC, loc.PkgPath, loc.File, loc.Line, loc.Column) } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { // reserve attach() so we can support it later. panic("attach() not yet supported") } } else { - // Already handled, added "add nilrealm" + // Already handled, added XTYPE_ADD_NILREALM // from the "cross" case above. if n.WithCross { // Is a cross(fn)(...) call. @@ -212,7 +211,7 @@ func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { // cannot be resolved statically defer func() { recover() - //fmt.Println("FAILED TO EVALSTATIC", n.Func, r) + // fmt.Println("FAILED TO EVALSTATIC", n.Func, r) }() // try to evaluate n.Func. tv = m.EvalStatic(last, n.Func) @@ -226,13 +225,13 @@ func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { if cv.IsCrossing() { // Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - addXItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXform1(pn, XTYPE_ADD_CURCALL, loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) } case *BoundMethodValue: if cv.IsCrossing() { // Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - addXItem(pn, "add curcall", loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXform1(pn, XTYPE_ADD_CURCALL, loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) } } } @@ -245,18 +244,49 @@ func FindXItemsGno0p9(store Store, pn *PackageNode, bn BlockNode) { }) } -const ATTR_GNO0P9_XITEMS = "ATTR_GNO0P9_XITEMS" +type xtype string + +const ( + XTYPE_ADD_CURCALL xtype = "ADD_CURCALL" + XTYPE_ADD_CURFUNC = "ADD_CURFUNC" + XTYPE_ADD_NILREALM = "ADD_NILREALM" +) + +const ATTR_GNO0P9_XFORMS = "ATTR_GNO0P9_XFORMS" -// t: type, p: pkgpath, f: filename, l: line, c: column -func addXItem(n Node, t string, p string, f string, l int, c int) { - x, _ := n.GetAttribute(ATTR_GNO0P9_XITEMS).(map[string]string) // p/f:l:c -> t - if x == nil { - x = make(map[string]string) - n.SetAttribute(ATTR_GNO0P9_XITEMS, x) +// Called from FindXformsGno0p9(). +// t: xtype, p: pkgpath, f: filename, l: line, c: column +func addXform1(n Node, x xtype, p string, f string, l int, c int) { + xforms1, _ := n.GetAttribute(ATTR_GNO0P9_XFORMS).(map[string]struct{}) // key = p/f:l:c+t + if xforms1 == nil { + xforms1 = make(map[string]struct{}) + n.SetAttribute(ATTR_GNO0P9_XFORMS, xforms1) + } + xform1 := fmt.Sprintf("%s/%s:%d:%d+%s", p, f, l, c, x) + if _, exists := xforms1[xform1]; exists { + panic("cannot trample existing item") + } + xforms1[xform1] = struct{}{} + fmt.Printf("xpiling to Gno 0.9: +%q\n", xform1) +} + +// Called from transpileGno0p9_part1 to translate p/f:l:c+t to n. +func addXform2IfMatched( + xforms1 map[string]struct{}, + xforms2 map[ast.Node]string, + gon ast.Node, + pkgPath, fname string, line, col int, + x xtype) { + + xform1 := fmt.Sprintf("%s/%s:%d:%d+%s", + pkgPath, fname, line, col, x) + if _, exists := xforms1[xform1]; exists { + if old, exists := xforms2[gon]; exists { + fmt.Println("xform2 already exists. old:", old, "new:", xform1) + panic("oops, need to refactor xforms2 to allow multiple xforms per node?") + } + xforms2[gon] = xform1 } - key := fmt.Sprintf("%s/%s:%d:%d", p, f, l, c) - x[key] = t - fmt.Printf("Gno 0.9 transpile +%s:%s\n", t, key) } // ======================================== @@ -267,34 +297,28 @@ func addXItem(n Node, t string, p string, f string, l int, c int) { // // Args: // - dir: where to write to. -// - xform: result of FindGno0p9XItems(). -func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) error { +// - xforms1: result of FindGno0p9Xforms(). +func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct{}) error { // Return if gno.mod is current. var mod *gnomod.File var err error mod, err = ParseCheckGnoMod(mpkg) if err == nil { - return nil // already up-to-date. + if mod.Gno.Version != "0.0" { + return fmt.Errorf("cannot transpile to gno 0.9: not gno 0.0") + } } // Go parse and collect files from mpkg. gofset := token.NewFileSet() var errs error + var xall int = 0 // number translated from part 1 for _, mfile := range mpkg.Files { // Ignore non-gno files. if !strings.HasSuffix(mfile.Name, ".gno") { continue } - /* - // Ignore _test/_filetest.gno files unless testing. - if !testing { - if strings.HasSuffix(mfile.Name, "_test.gno") || - strings.HasSuffix(mfile.Name, "_filetest.gno") { - continue - } - } - */ // Go parse file. const parseOpts = parser.ParseComments | parser.DeclarationErrors | @@ -308,14 +332,15 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) errs = multierr.Append(errs, err) continue } - // Transpile Part 1: re-key xform by ast.Node. - xform2, err := transpileGno0p9_part1(mpkg.Path, gofset, mfile.Name, gof, xform) + // Transpile Part 1: re-key xforms1 by ast.Node. + xnum, xforms2, err := transpileGno0p9_part1(mpkg.Path, gofset, mfile.Name, gof, xforms1) if err != nil { errs = multierr.Append(errs, err) continue } + xall += xnum // Transpile Part 2: main Go AST transform for Gno 0.9. - if err := transpileGno0p9_part2(mpkg.Path, gofset, mfile.Name, gof, xform2); err != nil { + if err := transpileGno0p9_part2(mpkg.Path, gofset, mfile.Name, gof, xforms2); err != nil { errs = multierr.Append(errs, err) continue } @@ -330,6 +355,12 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) } // END processing all memfiles. + // Ensure that all xforms were translated. + if xall != len(xforms1) { + // this is likely some bug in find* or part 1. + panic("some xform items were not translated") + } + // Write version to mod and to memfile named "gno.mod". mod.SetGno(GnoVersion) mpkg.SetFile("gno.mod", mod.WriteString()) @@ -339,55 +370,99 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xform map[string]string) return err } -// Transpile Step 1: re-key xform by ast.Node. +// Transpile Step 1: re-key xforms1 by ast.Node. // -// We can't just apply as we encounter matches in xform unfortunately because -// it causes the lines to shift. So we first convert xform into a map keyed +// We can't just apply as we encounter matches in xforms1 unfortunately because +// it causes the lines to shift. So we first convert xforms1 into a map keyed // by node and then do the actual transpiling in step 2. -func transpileGno0p9_part1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xform map[string]string) (xform2 map[ast.Node]string, err error) { - xform2 = make(map[ast.Node]string, len(xform)) +// +// Results: +// - xfound: number of items matched for file with name `fname` (for integrity) +func transpileGno0p9_part1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xforms1 map[string]struct{}) (xfound int, xforms2 map[ast.Node]string, err error) { + xforms2 = make(map[ast.Node]string, len(xforms1)) - astutil.Apply(f, func(c *astutil.Cursor) bool { + if len(xforms1) == 0 { + return 0, nil, nil // nothing to translate. + } + astutil.Apply(f, func(c *astutil.Cursor) bool { // Main switch on c.Node() type. switch n := c.Node().(type) { case *ast.FuncLit: pos := n.Pos() posn := fs.Position(pos) line, col := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) - if xform != nil && xform[key] == "add curfunc" { - xform2[n] = "add curfunc" - } + addXform2IfMatched( + xforms1, xforms2, n, + pkgPath, fname, line, col, + XTYPE_ADD_CURFUNC) case *ast.FuncDecl: pos := n.Pos() posn := fs.Position(pos) line, col := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) - if xform != nil && xform[key] == "add curfunc" { - xform2[n] = "add curfunc" - } + addXform2IfMatched( + xforms1, xforms2, n, + pkgPath, fname, line, col, + XTYPE_ADD_CURFUNC) case *ast.CallExpr: pos := n.Pos() posn := fs.Position(pos) line, col := posn.Line, posn.Column - key := fmt.Sprintf("%s/%s:%d:%d", pkgPath, fname, line, col) if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { return true // can be superimposed with parent call. } - if xform != nil && xform[key] == "add curcall" { - xform2[n] = "add curcall" - } else if xform != nil && xform[key] == "add nilrealm" { - xform2[n] = "add nilrealm" - } + addXform2IfMatched( + xforms1, xforms2, n, + pkgPath, fname, line, col, + XTYPE_ADD_CURCALL) + addXform2IfMatched( + xforms1, xforms2, n, + pkgPath, fname, line, col, + XTYPE_ADD_NILREALM) } return true }, nil) - return xform2, err + + // Check that all xforms1 items were translated to xforms2. + xfound = checkXforms(xforms1, xforms2, fname) + return xfound, xforms2, err +} + +// Check that xforms1 items were translated to xforms2 items for file named fname. +// Returns the number of items matched for file. +func checkXforms(xforms1 map[string]struct{}, xforms2 map[ast.Node]string, fname string) int { + mismatch := false + found := 0 +XFORMS1_LOOP: + for xform1, _ := range xforms1 { + if !strings.Contains(xform1, "/"+fname) { + continue + } + for _, xform2 := range xforms2 { + if xform1 == xform2 { + // good. + found += 1 + continue XFORMS1_LOOP + } + } + fmt.Println("xform2 item not found for xform1:", xform1) + mismatch = true + } + if !mismatch { + return found // good + } + // Failed check. + for xform1, _ := range xforms1 { + fmt.Println("xform1:", xform1) + } + for n2, xform2 := range xforms2 { + fmt.Println("xform2:", xform2, n2) + } + panic("xforms1 and xforms2 don't match") } // The main Go AST transpiling logic to make Gno code Gno 0.9. -func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof *ast.File, xform map[ast.Node]string) (err error) { +func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof *ast.File, xforms2 map[ast.Node]string) (err error) { var lastLine = 0 var didRemoveCrossing = false @@ -398,14 +473,24 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof var getLine = func(pos token.Pos) int { return fs.Position(pos).Line } + var inXforms2 = func(gon ast.Node, x xtype) bool { + if xforms2 == nil { + return false + } + value := xforms2[gon] + if strings.HasSuffix(value, "+"+string(x)) { + return true + } + return false + } astutil.Apply(gof, func(c *astutil.Cursor) bool { // Handle newlines after crossing if didRemoveCrossing { - n := c.Node() - line := getLine(n.Pos()) - tf := fs.File(n.Pos()) + gon := c.Node() + line := getLine(gon.Pos()) + tf := fs.File(gon.Pos()) if lastLine < line { // lastLine - 1 is the deleted crossing(). tf.MergeLine(lastLine - 1) @@ -416,19 +501,19 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof } // Main switch on c.Node() type. - switch n := c.Node().(type) { + switch gon := c.Node().(type) { case *ast.Ident: - if n.Name == "realm_XXX_TRANSPILE" { + if gon.Name == "realm_XXX_TRANSPILE" { // Impostor varname 'realm' will become // renamed, so reclaim 'realm'. - n.Name = "realm" - } else if n.Name == "realm" { + gon.Name = "realm" + } else if gon.Name == "realm" { // Rename name to _realm to avoid conflict with new builtin "realm". // XXX: optimistic. - n.Name = "_realm" + gon.Name = "_realm" } case *ast.ExprStmt: - if ce, ok := n.X.(*ast.CallExpr); ok { + if ce, ok := gon.X.(*ast.CallExpr); ok { if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" { // Validate syntax. if len(ce.Args) != 0 { @@ -437,45 +522,56 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof // Delete statement 'crossing()'. c.Delete() didRemoveCrossing = true - setLast(n.End()) + setLast(gon.End()) return false } } case *ast.FuncLit: - if xform != nil && xform[n] == "add curfunc" { - n.Type.Params.List = append([]*ast.Field{&ast.Field{ + if inXforms2(gon, XTYPE_ADD_CURFUNC) { + gon.Type.Params.List = append([]*ast.Field{&ast.Field{ Names: []*ast.Ident{ast.NewIdent("cur")}, Type: ast.NewIdent("realm_XXX_TRANSPILE"), - }}, n.Type.Params.List...) + }}, gon.Type.Params.List...) + delete(xforms2, gon) } case *ast.FuncDecl: - if xform != nil && xform[n] == "add curfunc" { - n.Type.Params.List = append([]*ast.Field{&ast.Field{ + if inXforms2(gon, XTYPE_ADD_CURFUNC) { + gon.Type.Params.List = append([]*ast.Field{&ast.Field{ Names: []*ast.Ident{ast.NewIdent("cur")}, Type: ast.NewIdent("realm_XXX_TRANSPILE"), - }}, n.Type.Params.List...) + }}, gon.Type.Params.List...) + delete(xforms2, gon) } case *ast.CallExpr: - if xform != nil && xform[n] == "add curcall" { - n.Args = append([]ast.Expr{ast.NewIdent("cur")}, n.Args...) - } else if xform != nil && xform[n] == "add nilrealm" { - n.Args = append([]ast.Expr{ast.NewIdent("nil")}, n.Args...) + if inXforms2(gon, XTYPE_ADD_CURCALL) { + gon.Args = append([]ast.Expr{ast.NewIdent("cur")}, gon.Args...) + delete(xforms2, gon) + } else if inXforms2(gon, XTYPE_ADD_NILREALM) { + gon.Args = append([]ast.Expr{ast.NewIdent("nil")}, gon.Args...) + delete(xforms2, gon) } - if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { + if id, ok := gon.Fun.(*ast.Ident); ok && id.Name == "cross" { // Replace expression 'cross(x)' by 'x'. // In Gno 0.9 @cross decorator is used instead. - var gon ast.Node - if len(n.Args) == 1 { - gon = n.Args[0] + if len(gon.Args) == 1 { + c.Replace(gon.Args[0]) } else { err = errors.New("cross called with invalid parameters") } - c.Replace(gon) return true } } return true }, nil) + + // Verify that all xforms2 items were consumed. + if len(xforms2) > 0 { + for gon, xform2 := range xforms2 { + fmt.Println("left over:", xform2, gon) + } + panic("Xform items left over") + } + return err } diff --git a/gnovm/pkg/gnomod/file.go b/gnovm/pkg/gnomod/file.go index 144afbd8014..4607e539739 100644 --- a/gnovm/pkg/gnomod/file.go +++ b/gnovm/pkg/gnomod/file.go @@ -28,6 +28,14 @@ type File struct { Syntax *modfile.FileSyntax } +func (f *File) GetGno() (version string) { + if f.Gno == nil { + return "0.0" + } else { + return f.Gno.Version + } +} + func (f *File) SetGno(version string) { if f.Syntax == nil { f.Syntax = new(modfile.FileSyntax) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 7509e7eb781..0888f95621b 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -62,7 +62,6 @@ func StoreWithOptions( m *gno.Machine, mpkg *std.MemPackage, save bool) ( pn *gno.PackageNode, pv *gno.PackageValue) { if opts.PreprocessOnly { - fmt.Println("WILL PROCESS", mpkg.Path) // In order to translate into a newer Gno version with // the preprocessor make a slight modifications to the // AST. This needs to happen even for imports, because diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 976c9c208ab..279be4d084c 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -193,8 +193,9 @@ func (mpkg *MemPackage) IsEmpty() bool { // Write all files into dir. func (mpkg *MemPackage) WriteTo(dir string) error { + fmt.Printf("writing mempackage to %q:\n", dir) for _, mfile := range mpkg.Files { - fmt.Printf("MemPackage.WriteTo(%s) (%d) bytes written\n", mfile.Name, len(mfile.Body)) + fmt.Printf(" - %s (%d bytes)\n", mfile.Name, len(mfile.Body)) fpath := filepath.Join(dir, mfile.Name) err := ioutil.WriteFile(fpath, []byte(mfile.Body), 0644) if err != nil { @@ -213,6 +214,14 @@ func (mpkg *MemPackage) Print() error { return nil } +// Return a list of all file names. +func (mpkg *MemPackage) FileNames() (fnames []string) { + for _, mfile := range mpkg.Files { + fnames = append(fnames, mfile.Name) + } + return +} + const licenseName = "LICENSE" // Splits a path into the dir and filename. From 7cf9fc103f6ab757178e4476f798fff38ef90e78 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 11 May 2025 20:14:13 -0700 Subject: [PATCH 12/83] ... --- gnovm/pkg/test/imports.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 0888f95621b..bcd414b480c 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -62,18 +62,25 @@ func StoreWithOptions( m *gno.Machine, mpkg *std.MemPackage, save bool) ( pn *gno.PackageNode, pv *gno.PackageValue) { if opts.PreprocessOnly { - // In order to translate into a newer Gno version with - // the preprocessor make a slight modifications to the - // AST. This needs to happen even for imports, because - // the preprocessor requries imports also preprocessed. - const wtests = false // Tests don't matter for imports. - gofset, gofs, errs := gno.GoParseMemPackage(mpkg, wtests) - if errs != nil { - panic(fmt.Errorf("test store parsing: %w", errs)) + // Check the gno.mod gno version. + mod, err := gno.ParseCheckGnoMod(mpkg) + if err != nil { + panic(fmt.Errorf("test store parsing gno.mod: %w", err)) } - errs = gno.PrepareGno0p9(gofset, gofs, mpkg) - if errs != nil { - panic(fmt.Errorf("test store preparing AST: %w", errs)) + if mod.GetGno() == "0.0" { + // In order to translate into a newer Gno version with + // the preprocessor make a slight modifications to the + // AST. This needs to happen even for imports, because + // the preprocessor requries imports also preprocessed. + const wtests = false // Tests don't matter for imports. + gofset, gofs, errs := gno.GoParseMemPackage(mpkg, wtests) + if errs != nil { + panic(fmt.Errorf("test store parsing: %w", errs)) + } + errs = gno.PrepareGno0p9(gofset, gofs, mpkg) + if errs != nil { + panic(fmt.Errorf("test store preparing AST: %w", errs)) + } } m.Store.AddMemPackage(mpkg) return m.PreprocessFiles( From 07086adfbbd46ae4063609a0f6d18abe0a236ab9 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 11 May 2025 21:00:33 -0700 Subject: [PATCH 13/83] ... --- gnovm/adr/lint_transpile.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/adr/lint_transpile.md b/gnovm/adr/lint_transpile.md index 51260eab2e5..8f33c81b5f2 100644 --- a/gnovm/adr/lint_transpile.md +++ b/gnovm/adr/lint_transpile.md @@ -5,8 +5,8 @@ The steps of Gno 0.0 --> Gno 0.9 transpiling. 4. `Prepare*()`: minimal Go AST mutations for Gno VM compat. 5. `gno.MustParseFile()`: re-parse prepared AST 6. `m.PreprocessFiles()`: normal Gno AST preprocessing. - 7. `FindXforms*()`: Gno AST static analaysis to produce xitems. - 8. `Transpile*()` Part 1: re-key xitems by Go Node before step 2 line changes. + 7. `FindXforms*()`: Gno AST static analaysis to produce line-based xforms. + 8. `Transpile*()` Part 1: re-key xforms from line-based to Go node-based. 9. `Transpile*()` Part 2: main Go AST mutations for Gno upgrade. 10. `mpkg.WriteTo()`: write mem package to disk. From 7fcfae414c55f32c550f13afbed8d667afc58d15 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 12 May 2025 07:01:12 -0700 Subject: [PATCH 14/83] ... --- gnovm/pkg/gnolang/files_test.go | 8 +- gnovm/pkg/gnolang/go2gno.go | 65 +++--- gnovm/pkg/gnolang/machine.go | 3 +- gnovm/pkg/gnolang/nodes.go | 67 ++----- gnovm/pkg/gnolang/nodes_span.go | 242 +++++++++++++++++++++++ gnovm/pkg/gnolang/preprocess.go | 64 +++--- gnovm/pkg/gnolang/transpile_gno0p9.go | 69 +++---- gnovm/pkg/gnolang/validate_mempackage.go | 15 +- gnovm/pkg/test/filetest.go | 22 ++- tm2/pkg/std/memfile.go | 4 +- 10 files changed, 395 insertions(+), 164 deletions(-) create mode 100644 gnovm/pkg/gnolang/nodes_span.go diff --git a/gnovm/pkg/gnolang/files_test.go b/gnovm/pkg/gnolang/files_test.go index 4b6b7bdc6b0..627d7157d84 100644 --- a/gnovm/pkg/gnolang/files_test.go +++ b/gnovm/pkg/gnolang/files_test.go @@ -54,18 +54,18 @@ func TestFiles(t *testing.T) { // sharedOpts is used for all "short" tests. sharedOpts := newOpts() - dir := "../../tests/" + dir := "../../tests/files" fsys := os.DirFS(dir) - err = fs.WalkDir(fsys, "files", func(path string, de fs.DirEntry, err error) error { + err = fs.WalkDir(fsys, ".", func(path string, de fs.DirEntry, err error) error { switch { case err != nil: return err - case path == "files/extern": + case path == "extern": return fs.SkipDir case de.IsDir(): return nil } - subTestName := path[len("files/"):] + subTestName := path isLong := strings.HasSuffix(path, "_long.gno") if isLong && testing.Short() { t.Run(subTestName, func(t *testing.T) { diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index d43cc9df703..a39f74f7178 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -114,29 +114,38 @@ func ParseFile(filename string, body string) (fn *FileNode, err error) { // Print the imports from the file's AST. // spew.Dump(f) - // recover from Go2Gno. - // NOTE: Go2Gno is best implemented with panics due to inlined toXYZ() calls. - defer func() { - if r := recover(); r != nil { - if rerr, ok := r.(error); ok { - err = errors.Wrap(rerr, "parsing file") - } else { - err = errors.New(fmt.Sprintf("%v", r)).Stacktrace() + // XXX Disable this when running with -debug or similar. + if true { + // Recover from Go2Gno. + // NOTE: Go2Gno is best implemented with panics due to inlined toXYZ() calls. + defer func() { + if r := recover(); r != nil { + if rerr, ok := r.(error); ok { + err = errors.Wrap(rerr, "parsing file") + } else { + err = errors.New(fmt.Sprintf("%v", r)).Stacktrace() + } + return } - return - } - }() - // parse with Go2Gno. + }() + } + // Parse with Go2Gno. fn = Go2Gno(fs, astf).(*FileNode) fn.Name = Name(filename) return fn, nil } -func setLoc(fs *token.FileSet, astn ast.Node, n Node) Node { - pos := astn.Pos() - posn := fs.Position(pos) - n.SetLine(posn.Line) - n.SetColumn(posn.Column) +// setSpan() will not attempt to overwrite an existing span. +// This usually happens when an inner node is passed outward, +// in which case we want to keep the original specificity. +func setSpan(fs *token.FileSet, astn ast.Node, n Node) Node { + if n.GetSpan().IsZero() { + pos := astn.Pos() + posn := fs.Position(pos) + end := astn.End() + endn := fs.Position(end) + n.SetSpan(Span{Pos: Pos{posn.Line, posn.Column}, End: Pos{endn.Line, endn.Column}}) + } return n } @@ -158,7 +167,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { if fs != nil { defer func() { if n != nil { - setLoc(fs, gon, n) + setSpan(fs, gon, n) } }() } @@ -360,7 +369,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { thenStmt := IfCaseStmt{ Body: toBody(fs, gon.Body), } - setLoc(fs, gon.Body, &thenStmt) + setSpan(fs, gon.Body, &thenStmt) ess := []Stmt(nil) if gon.Else != nil { if _, ok := gon.Else.(*ast.BlockStmt); ok { @@ -373,7 +382,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { Body: ess, } if gon.Else != nil { - setLoc(fs, gon.Else, &elseStmt) + setSpan(fs, gon.Else, &elseStmt) } return &IfStmt{ Init: toSimp(fs, gon.Init), @@ -665,7 +674,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Type: tipe, IsAlias: alias, } - setLoc(fs, s, td) + setSpan(fs, s, td) ds = append(ds, td) case *ast.ValueSpec: if gd.Tok == token.CONST { @@ -698,7 +707,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Const: true, } cd.SetAttribute(ATTR_IOTA, si) - setLoc(fs, s, cd) + setSpan(fs, s, cd) ds = append(ds, cd) } else { var names []NameExpr @@ -717,7 +726,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { Values: values, Const: false, } - setLoc(fs, s, vd) + setSpan(fs, s, vd) ds = append(ds, vd) } case *ast.ImportSpec: @@ -729,7 +738,7 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { NameExpr: *Nx(toName(s.Name)), PkgPath: path, } - setLoc(fs, s, im) + setSpan(fs, s, im) ds = append(ds, im) default: panic(fmt.Sprintf( @@ -772,7 +781,7 @@ func toFields(fs *token.FileSet, fields ...*ast.Field) (ftxs []FieldTypeExpr) { Type: toExpr(fs, f.Type), Tag: toExpr(fs, f.Tag), } - setLoc(fs, f, &ftx) + setSpan(fs, f, &ftx) ftxs = append(ftxs, ftx) } else { // one or more named fields @@ -782,7 +791,7 @@ func toFields(fs *token.FileSet, fields ...*ast.Field) (ftxs []FieldTypeExpr) { Type: toExpr(fs, f.Type), Tag: toExpr(fs, f.Tag), } - setLoc(fs, f, &ftx) + setSpan(fs, f, &ftx) ftxs = append(ftxs, ftx) } } @@ -800,7 +809,7 @@ func toKeyValueExprs(fs *token.FileSet, elts []ast.Expr) (kvxs KeyValueExprs) { Key: nil, Value: toExpr(fs, x), } - setLoc(fs, x, &kvx) + setSpan(fs, x, &kvx) kvxs[i] = kvx } } @@ -836,6 +845,6 @@ func toSwitchClauseStmt(fs *token.FileSet, cc *ast.CaseClause) SwitchClauseStmt Cases: toExprs(fs, cc.List), Body: toStmts(fs, cc.Body), } - setLoc(fs, cc, &scs) + setSpan(fs, cc, &scs) return scs } diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index daa36ada98c..82e34a00929 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -224,7 +224,7 @@ func (m *Machine) PreprocessAllFilesAndSaveBlockNodes() { //---------------------------------------- // top level Run* methods. -// Parses files, sets the package if doesn't exist, runs files, saves mempkg +// Sorts and parses files, sets the package if doesn't exist, runs files, saves mempkg // and corresponding package node, package value, and types to store. Save // is set to false for tests where package values may be native. func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { @@ -234,6 +234,7 @@ func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode if bm.StorageEnabled { defer bm.FinishStore() } + memPkg.Sort() return m.runMemPackage(memPkg, save, false) } diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 5b3e9658609..a7bca79b844 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -113,33 +113,6 @@ const ( type Name string -// ---------------------------------------- -// Location -// Acts as an identifier for nodes. - -type Location struct { - PkgPath string - File string - Line int - Column int -} - -func (loc Location) String() string { - return fmt.Sprintf("%s/%s:%d:%d", - loc.PkgPath, - loc.File, - loc.Line, - loc.Column, - ) -} - -func (loc Location) IsZero() bool { - return loc.PkgPath == "" && - loc.File == "" && - loc.Line == 0 && - loc.Column == 0 -} - // ---------------------------------------- // Attributes // All nodes have attributes for general analysis purposes. @@ -164,27 +137,11 @@ const ( ATTR_PACKAGE_DECL GnoAttribute = "ATTR_PACKAGE_DECL" ) +// Embedded in each Node. type Attributes struct { - Line int - Column int - Label Name - data map[GnoAttribute]any // not persisted -} - -func (attr *Attributes) GetLine() int { - return attr.Line -} - -func (attr *Attributes) SetLine(line int) { - attr.Line = line -} - -func (attr *Attributes) GetColumn() int { - return attr.Column -} - -func (attr *Attributes) SetColumn(column int) { - attr.Column = column + Span // Node.Line is the start. + Label Name + data map[GnoAttribute]any // not persisted } func (attr *Attributes) GetLabel() Name { @@ -220,6 +177,14 @@ func (attr *Attributes) DelAttribute(key GnoAttribute) { delete(attr.data, key) } +func (attr *Attributes) String() string { + panic("should not use") // node should override Pos/Span/Location methods. +} + +func (attr *Attributes) IsZero() bool { + panic("should not use") // node should override Pos/Span/Location methods. +} + // ---------------------------------------- // Node @@ -228,9 +193,9 @@ type Node interface { String() string Copy() Node GetLine() int - SetLine(int) GetColumn() int - SetColumn(int) + GetSpan() Span + SetSpan(Span) // once. GetLabel() Name SetLabel(Name) HasAttribute(key GnoAttribute) bool @@ -1261,7 +1226,7 @@ func MustReadMemPackage(dir string, pkgPath string) *std.MemPackage { // lowercase, and must start with a letter). // // XXX TODO pkgPath should instead be derived by inspecting the contents, among them -// the gno.mod fule. +// the gno.mod file. func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, error) { mpkg := &std.MemPackage{Path: pkgPath} var pkgName Name @@ -1426,8 +1391,6 @@ type PackageNode struct { func PackageNodeLocation(path string) Location { return Location{ PkgPath: path, - File: "", - Line: 0, } } diff --git a/gnovm/pkg/gnolang/nodes_span.go b/gnovm/pkg/gnolang/nodes_span.go new file mode 100644 index 00000000000..ca6508b7ef4 --- /dev/null +++ b/gnovm/pkg/gnolang/nodes_span.go @@ -0,0 +1,242 @@ +package gnolang + +import ( + "fmt" + "go/ast" + "go/token" + "strings" +) + +/* ======================================== +``` +{ + Attributes{ + Label Name + Span{ + Pos{ + Line int + Column int + End:Pos{ + Line int + Column int + StaticBlock{ + Loc:Location{ + Span{ +{ + Attributes{ + Label Name + Span{ + Pos{ + Line int + Column int + End:Pos{ + Line int + Column int +``` +======================================== */ + +// Pos(isition) +type Pos struct { + Line int + Column int +} + +func (p Pos) GetLine() int { + return p.Line +} + +func (p Pos) GetColumn() int { + return p.Column +} + +func (p1 Pos) Compare(p2 Pos) int { + switch { + case p1.Line < p2.Line: + return -1 + case p1.Line == p2.Line: + break + case p1.Line > p2.Line: + return 1 + default: + panic("should not happen") + } + switch { + case p1.Column < p2.Column: + return -1 + case p1.Column == p2.Column: + return 0 + case p1.Column > p2.Column: + return 1 + default: + panic("should not happen") + } +} + +// Overridden by Attributes.String(). +func (p Pos) String() string { + return fmt.Sprintf("%d:%d", p.Line, p.Column) +} + +// Overridden by Attributes.IsZero(). +// NOTE: DO NOT CHANGE. +func (p Pos) IsZero() bool { + return p == Pos{} +} + +// ---------------------------------------- +// Span +// Has a start (pos) and an end. +type Span struct { + Pos // start + End Pos + Num int // positive if conflicts. +} + +func SpanFromGo(gofs *token.FileSet, gon ast.Node) Span { + pos := gon.Pos() + end := gon.End() + posn := gofs.Position(pos) + endn := gofs.Position(end) + return Span{ + Pos: Pos{posn.Line, posn.Column}, + End: Pos{endn.Line, endn.Column}, + } +} + +func (s Span) GetSpan() Span { + return s +} + +// If you need to update the span/pos/location of a node it should be re-parsed +// from an updated AST. This is important because location is used as identity. +// Anyone with a node can still mutate these fields directly; the method guides. +func (s1 *Span) SetSpan(s2 Span) { + if !s1.IsZero() && (*s1 != s2) { + panic(".Span can ony be set once. s1:" + s1.String() + " s2:" + s2.String()) + } + *s1 = s2 +} + +// Overridden by Attributes.String(). +func (s Span) String() string { + if s.Pos.Line == s.End.Line { + return fmt.Sprintf("%d:%d-%d%s", + s.Pos.Line, s.Pos.Column, s.End.Column, + strings.Repeat("'", s.Num), // e.g. 1:1-12' + ) + } else { + return fmt.Sprintf("%s-%s%s", + s.Pos.String(), s.End.String(), + strings.Repeat("'", s.Num), // e.g. 1:1-3:4''' + ) + } +} + +// XXX delete this after fixing all tests. +func (s Span) StringXXX() string { + return fmt.Sprintf("%d:%d", + s.Pos.Line, s.Pos.Column) +} + +// Overridden by Attributes.IsZero(). +// NOTE: DO NOT CHANGE. +func (s Span) IsZero() bool { + return s == Span{} +} + +// Suitable for Node. Less means earlier / higher level. +// Start (.Pos) determines node order before .End/ .Num, +// then the end (greater means containing, thus sooner), +// then the num (smaller means containing, thus sooner). +func (s1 Span) Compare(s2 Span) int { + switch s1.Pos.Compare(s2.Pos) { + case -1: // s1.Pos < s2.Pos + return -1 + case 0: // s1.Pos == s2.Pos + break + case 1: // s1.Pos > s2.Pos + return 1 + default: + panic("should not happen") + } + switch s1.End.Compare(s2.End) { + case -1: // s1.End < s2.End + return 1 // see comment + case 0: // s1.End == s2.End + break + case 1: + return -1 // see comment + default: + panic("should not happen") + } + switch { + case s1.Num < s2.Num: + return -1 + case s1.Num == s2.Num: + return 0 + case s1.Num > s2.Num: + return 1 + default: + panic("should not happen") + } +} + +// Union() returns a span for a new containing node w/ .Num possibly negative. +// NOTE: Span union math based on lines and columns, not the same math as for +// 2D container boxes. 2D has cardinality of 2, and span has cardinality of 1. +// See Span.Compare() to see a quirk where a greater end can mean lesser span. +// (we assume our 3D world has a cardinality of 3 but what if it is really 2?) +func (s1 Span) Union(s2 Span) (res Span) { + if s1.Pos.Compare(s2.Pos) < 0 { + res.Pos = s1.Pos + } else { + res.Pos = s2.Pos + } + if s1.End.Compare(s2.End) < 0 { + res.End = s2.End + } else { + res.End = s1.End + } + // Only when s1 == s2 does .Num get set. + if s1.Pos == s2.Pos && s1.End == s2.End { + res.Num = min(s1.Num, s2.Num) - 1 // maybe < 0. + } else { + res.Num = 0 // starts with zero. + } + return +} + +// ---------------------------------------- +// Location +// A Location is also an identifier for nodes. +// BlockNodes have these, while all Nodes have only .Span. +// (.Span field is duplicated in Node.Attributes and BlockNode.Location) +type Location struct { + PkgPath string + File string + Span +} + +// XXX Delete this after fixing all tests. +func (loc Location) StringXXX() string { + return fmt.Sprintf("%s/%s:%s", + loc.PkgPath, + loc.File, + loc.Span.StringXXX(), + ) +} + +// Overridden by Attributes.String(). +func (loc Location) String() string { + return fmt.Sprintf("%s/%s:%s", + loc.PkgPath, + loc.File, + loc.Span.String(), + ) +} + +// Overridden by Attributes.IsZero(). +// NOTE: DO NOT CHANGE. +func (loc Location) IsZero() bool { + return loc == Location{} +} diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 7c9455d75e2..ae89dde55c3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -394,7 +394,7 @@ func doRecover(stack []BlockNode, n Node) { if ok { err = errors.Wrap(rerr, loc.String()) } else { - err = fmt.Errorf("%s: %v", loc.String(), r) + err = fmt.Errorf("%s: %v", loc.StringXXX(), r) // XXX revert to String(). } // Re-throw the error after wrapping it with the preprocessing stack information. @@ -1969,7 +1969,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { Op: DEFINE, Rhs: n.Rhs, } - dsx.SetLine(n.Line) + // dsx.SetSpan(n.GetSpan()) dsx = Preprocess(store, last, dsx).(*AssignStmt) // step3: @@ -1987,7 +1987,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { Op: ASSIGN, Rhs: copyExprs(tmpExprs), } - asx.SetLine(n.Line) + // asx.SetSpan(n.GetSpan()) asx = Preprocess(store, last, asx).(*AssignStmt) // step4: @@ -3365,7 +3365,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { TypedValue: cv, } } - cx.SetLine(x.GetLine()) + // cx.SetSpan(x.GetSpan()) cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) return cx @@ -3374,7 +3374,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { func constType(source Expr, t Type) *constTypeExpr { cx := &constTypeExpr{Source: source} cx.Type = t - cx.SetLine(source.GetLine()) + // cx.SetSpan(source.GetSpan()) cx.SetAttribute(ATTR_PREPROCESSED, true) return cx } @@ -5389,23 +5389,44 @@ func isLocallyDefined2(bn BlockNode, n Name) bool { // ---------------------------------------- // setNodeLines & setNodeLocations -func setNodeLines(n Node) { - lastLine := 0 - lastColumn := 0 - Transcribe(n, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { - if stage != TRANS_ENTER { +func setNodeLines(nn Node) { + var all Span // if nn has no span defined, derive one from its contents. + Transcribe(nn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + switch stage { + case TRANS_ENTER: + var nspan = n.GetSpan() + if nspan.IsZero() { + if len(ns) == 0 { + // Handled by TRANS_LEAVE. Case A. + return n, TRANS_CONTINUE + } + var lastSpan = ns[len(ns)-1].GetSpan() + if lastSpan.IsZero() { + // Handled by TRANS_LEAVE too. Case B. + return n, TRANS_CONTINUE + } else { + // Derive from parent with .Num++. + nspan = lastSpan + nspan.Num += 1 + n.SetSpan(nspan) + return n, TRANS_CONTINUE + } + } else { + // Expand all with nspan. + all = all.Union(nspan) + return n, TRANS_CONTINUE + } + case TRANS_LEAVE: + // TODO: Validate that all spans of elements are + // strictly contained. + var nspan = n.GetSpan() + if nspan.IsZero() { + // Case A: len(ns) == 0 + // Case b: len(ns) > 0. + n.SetSpan(all) + } return n, TRANS_CONTINUE } - line, column := n.GetLine(), n.GetColumn() - if line == 0 { - line, column = lastLine, lastColumn - } else if line != lastLine { - lastLine, lastColumn = line, column - } else if column != lastColumn { - /*lastLine,*/ lastColumn = /*line,*/ column - } - n.SetLine(line) - n.SetColumn(column) return n, TRANS_CONTINUE }) } @@ -5426,8 +5447,7 @@ func setNodeLocations(pkgPath string, fileName string, n Node) { loc := Location{ PkgPath: pkgPath, File: fileName, - Line: bn.GetLine(), - Column: bn.GetColumn(), + Span: bn.GetSpan(), } bn.SetLocation(loc) } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 25133702ab7..472664601c8 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -181,14 +181,14 @@ func FindXformsGno0p9(store Store, pn *PackageNode, bn BlockNode) { panic("cross(fn) must be followed by a call") } loc := last.GetLocation() - addXform1(pn, XTYPE_ADD_NILREALM, loc.PkgPath, loc.File, pc.GetLine(), pc.GetColumn()) + addXform1(pn, loc.PkgPath, loc.File, pc.GetSpan(), XTYPE_ADD_NILREALM) } else if fv.PkgPath == uversePkgPath && fv.Name == "crossing" { if !IsRealmPath(pn.PkgPath) { panic("crossing() is only allowed in realm packages") } // Add `cur realm` as first argument to func decl. loc := last.GetLocation() - addXform1(pn, XTYPE_ADD_CURFUNC, loc.PkgPath, loc.File, loc.Line, loc.Column) + addXform1(pn, loc.PkgPath, loc.File, loc.Span, XTYPE_ADD_CURFUNC) } else if fv.PkgPath == uversePkgPath && fv.Name == "attach" { // reserve attach() so we can support it later. panic("attach() not yet supported") @@ -225,13 +225,13 @@ func FindXformsGno0p9(store Store, pn *PackageNode, bn BlockNode) { if cv.IsCrossing() { // Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - addXform1(pn, XTYPE_ADD_CURCALL, loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXform1(pn, loc.PkgPath, loc.File, n.GetSpan(), XTYPE_ADD_CURCALL) } case *BoundMethodValue: if cv.IsCrossing() { // Not cross-called, so add `cur` as first argument. loc := last.GetLocation() - addXform1(pn, XTYPE_ADD_CURCALL, loc.PkgPath, loc.File, n.GetLine(), n.GetColumn()) + addXform1(pn, loc.PkgPath, loc.File, n.GetSpan(), XTYPE_ADD_CURCALL) } } } @@ -255,14 +255,15 @@ const ( const ATTR_GNO0P9_XFORMS = "ATTR_GNO0P9_XFORMS" // Called from FindXformsGno0p9(). -// t: xtype, p: pkgpath, f: filename, l: line, c: column -func addXform1(n Node, x xtype, p string, f string, l int, c int) { - xforms1, _ := n.GetAttribute(ATTR_GNO0P9_XFORMS).(map[string]struct{}) // key = p/f:l:c+t +// p: pkgpath, f: filename +func addXform1(n Node, p string, f string, s Span, x xtype) { + // key: p/f:s+x + xforms1, _ := n.GetAttribute(ATTR_GNO0P9_XFORMS).(map[string]struct{}) if xforms1 == nil { xforms1 = make(map[string]struct{}) n.SetAttribute(ATTR_GNO0P9_XFORMS, xforms1) } - xform1 := fmt.Sprintf("%s/%s:%d:%d+%s", p, f, l, c, x) + xform1 := fmt.Sprintf("%s/%s:%v+%s", p, f, s, x) if _, exists := xforms1[xform1]; exists { panic("cannot trample existing item") } @@ -270,19 +271,16 @@ func addXform1(n Node, x xtype, p string, f string, l int, c int) { fmt.Printf("xpiling to Gno 0.9: +%q\n", xform1) } -// Called from transpileGno0p9_part1 to translate p/f:l:c+t to n. +// Called from transpileGno0p9_part1 to translate p/f:l:c+x to n. func addXform2IfMatched( xforms1 map[string]struct{}, xforms2 map[ast.Node]string, - gon ast.Node, - pkgPath, fname string, line, col int, - x xtype) { + gon ast.Node, p string, f string, s Span, x xtype) { - xform1 := fmt.Sprintf("%s/%s:%d:%d+%s", - pkgPath, fname, line, col, x) + xform1 := fmt.Sprintf("%s/%s:%v+%s", p, f, s, x) if _, exists := xforms1[xform1]; exists { - if old, exists := xforms2[gon]; exists { - fmt.Println("xform2 already exists. old:", old, "new:", xform1) + if prior, exists := xforms2[gon]; exists { + fmt.Println("xform2 already exists. prior:", prior, "new:", xform1) panic("oops, need to refactor xforms2 to allow multiple xforms per node?") } xforms2[gon] = xform1 @@ -378,51 +376,44 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct // // Results: // - xfound: number of items matched for file with name `fname` (for integrity) -func transpileGno0p9_part1(pkgPath string, fs *token.FileSet, fname string, f *ast.File, xforms1 map[string]struct{}) (xfound int, xforms2 map[ast.Node]string, err error) { +func transpileGno0p9_part1(pkgPath string, gofs *token.FileSet, fname string, gof *ast.File, xforms1 map[string]struct{}) (xfound int, xforms2 map[ast.Node]string, err error) { xforms2 = make(map[ast.Node]string, len(xforms1)) if len(xforms1) == 0 { return 0, nil, nil // nothing to translate. } - astutil.Apply(f, func(c *astutil.Cursor) bool { + astutil.Apply(gof, func(c *astutil.Cursor) bool { // Main switch on c.Node() type. - switch n := c.Node().(type) { + switch gon := c.Node().(type) { case *ast.FuncLit: - pos := n.Pos() - posn := fs.Position(pos) - line, col := posn.Line, posn.Column + span := SpanFromGo(gofs, gon) addXform2IfMatched( - xforms1, xforms2, n, - pkgPath, fname, line, col, + xforms1, xforms2, gon, + pkgPath, fname, span, XTYPE_ADD_CURFUNC) case *ast.FuncDecl: - pos := n.Pos() - posn := fs.Position(pos) - line, col := posn.Line, posn.Column + span := SpanFromGo(gofs, gon) addXform2IfMatched( - xforms1, xforms2, n, - pkgPath, fname, line, col, + xforms1, xforms2, gon, + pkgPath, fname, span, XTYPE_ADD_CURFUNC) case *ast.CallExpr: - pos := n.Pos() - posn := fs.Position(pos) - line, col := posn.Line, posn.Column - if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" { - return true // can be superimposed with parent call. - } + span := SpanFromGo(gofs, gon) addXform2IfMatched( - xforms1, xforms2, n, - pkgPath, fname, line, col, + xforms1, xforms2, gon, + pkgPath, fname, span, XTYPE_ADD_CURCALL) addXform2IfMatched( - xforms1, xforms2, n, - pkgPath, fname, line, col, + xforms1, xforms2, gon, + pkgPath, fname, span, XTYPE_ADD_NILREALM) } return true }, nil) + fmt.Println("COMPARE", len(xforms1), len(xforms2)) + // Check that all xforms1 items were translated to xforms2. xfound = checkXforms(xforms1, xforms2, fname) return xfound, xforms2, err diff --git a/gnovm/pkg/gnolang/validate_mempackage.go b/gnovm/pkg/gnolang/validate_mempackage.go index e156f540f31..b01119ebbd9 100644 --- a/gnovm/pkg/gnolang/validate_mempackage.go +++ b/gnovm/pkg/gnolang/validate_mempackage.go @@ -1,7 +1,6 @@ package gnolang import ( - "fmt" "regexp" "github.com/gnolang/gno/tm2/pkg/std" @@ -17,6 +16,7 @@ var ( // sub.domain.com/r/realm/path // sub.domain.com/p/package/path // See also tm2/pkg/std/memfile.go. + // XXX test exhaustively balanced futureproof vs restrictive. reGnoPkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:[a-z])(?:\/_?[a-z][a-z0-9_]*)+$`) reGnoPkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) ) @@ -26,10 +26,13 @@ func ValidateMemPackage(mpkg *std.MemPackage) error { if err != nil { return err } - if true && // none of these match... - !reGnoPkgPathURL.MatchString(mpkg.Path) && - !reGnoPkgPathStd.MatchString(mpkg.Path) { - return fmt.Errorf("invalid package/realm path %q", mpkg.Path) - } + /* + XXX Uncomment this once all tests pass. + if true && // none of these match... + !reGnoPkgPathURL.MatchString(mpkg.Path) && + !reGnoPkgPathStd.MatchString(mpkg.Path) { + return fmt.Errorf("invalid package/realm path %q", mpkg.Path) + } + */ return nil } diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index c346d90e534..74bdaa89e9d 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "path/filepath" "regexp" "runtime/debug" "slices" @@ -22,14 +23,14 @@ import ( // RunFiletest executes the program in source as a filetest. // If opts.Sync is enabled, and the filetest's golden output has changed, // the first string is set to the new generated content of the file. -func (opts *TestOptions) RunFiletest(filename string, source []byte) (string, error) { +func (opts *TestOptions) RunFiletest(fname string, source []byte) (string, error) { opts.outWriter.w = opts.Output opts.outWriter.errW = opts.Error - return opts.runFiletest(filename, source) + return opts.runFiletest(fname, source) } -func (opts *TestOptions) runFiletest(filename string, source []byte) (string, error) { +func (opts *TestOptions) runFiletest(fname string, source []byte) (string, error) { dirs, err := ParseDirectives(bytes.NewReader(source)) if err != nil { return "", fmt.Errorf("error parsing directives: %w", err) @@ -64,7 +65,7 @@ func (opts *TestOptions) runFiletest(filename string, source []byte) (string, er ReviveEnabled: true, }) defer m.Release() - result := opts.runTest(m, pkgPath, filename, source, opslog) + result := opts.runTest(m, pkgPath, fname, source, opslog) // updated tells whether the directives have been updated, and as such // a new generated filetest should be returned. @@ -223,9 +224,10 @@ type runResult struct { GoPanicStack []byte } -func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, content []byte, opslog io.Writer) (rr runResult) { +func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content []byte, opslog io.Writer) (rr runResult) { pkgName := gno.Name(pkgPath[strings.LastIndexByte(pkgPath, '/')+1:]) tcError := "" + fname = filepath.Base(fname) // Eagerly load imports. // This is executed using opts.Store, rather than the transaction store; @@ -237,7 +239,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Path: pkgPath, Files: []*std.MemFile{ {Name: "gno.mod", Body: "gno 0.9"}, - {Name: filename, Body: string(content)}, + {Name: fname, Body: string(content)}, }, }); err != nil { // NOTE: we perform this here, so we can capture the runResult. @@ -280,7 +282,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Path: pkgPath, Files: []*std.MemFile{ {Name: "gno.mod", Body: "gno 0.9"}, - {Name: filename, Body: string(content)}, + {Name: fname, Body: string(content)}, }, } // Validate Gno syntax and type check. @@ -295,7 +297,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte m.Store.SetCachePackage(pv) m.SetActivePackage(pv) m.Context.(*teststd.TestExecContext).OriginCaller = DefaultCaller - n := gno.MustParseFile(filename, string(content)) + n := gno.MustParseFile(fname, string(content)) m.RunFiles(n) m.RunMain() @@ -305,7 +307,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte // Remove filetest from name, as that can lead to the package not being // parsed correctly when using RunMemPackage. - filename = strings.ReplaceAll(filename, "_filetest", "") + fname = strings.ReplaceAll(fname, "_filetest", "") // save package using realm crawl procedure. memPkg := &std.MemPackage{ @@ -313,7 +315,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte Path: pkgPath, Files: []*std.MemFile{ {Name: "gno.mod", Body: "gno 0.9"}, - {Name: filename, Body: string(content)}, + {Name: fname, Body: string(content)}, }, } orig, tx := m.Store, m.Store.BeginTransaction(nil, nil, nil) diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 279be4d084c..fa653a7a772 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -18,9 +18,9 @@ const pkgPathLimit = 256 var ( // See also gnovm/pkg/gnolang/validate_mempackage.go. - reFileName = regexp.MustCompile(`^(([a-z0-9_]+|[A-Z0-9_]+)\.[a-z0-9_]{1,7}|LICENSE|README)$`) + reFileName = regexp.MustCompile(`^(([a-z0-9_\-]+|[A-Z0-9_\-]+)\.[a-z0-9_]{1,7}|LICENSE|README)$`) rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) - rePkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:p|r)(?:\/_?[a-z]+[a-z0-9_]*)+$`) + rePkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}(\/[a-z0-9\-_]+)+$`) rePkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) ) From ca1ebe0371e597928eee856214037df9e2c27def Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 12 May 2025 07:57:18 -0700 Subject: [PATCH 15/83] ... --- gnovm/pkg/gnolang/gnomod.go | 10 ++++++---- gnovm/pkg/test/imports.go | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index dacdd08e2c4..76662b93594 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -26,15 +26,17 @@ const ( // // Results: // - mod: the gno.mod file, or nil if not found. -// - err: wrapped error +// - err: wrapped error, or nil if file not found. func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { if IsStdlib(mpkg.Path) { // stdlib/extern packages are assumed up to date. mod, _ = gnomod.ParseBytes("/gno.mod", []byte(GnoModLatest)) - } else if mod, _ = gnomod.ParseMemPackage(mpkg); mod == nil { + } else if mpkg.GetFile("gno.mod") == nil { // gno.mod doesn't exist. - mod, _ = gnomod.ParseBytes(mpkg.Path+"/gno.mod", []byte(GnoModDefault)) - err = fmt.Errorf("%s/gno.mod: not found", mpkg.Path) + return nil, nil + } else if mod, err = gnomod.ParseMemPackage(mpkg); err != nil { + // error parsing gno.mod. + err = fmt.Errorf("%s/gno.mod: parse error %q", mpkg.Path, err) } else if mod.Gno == nil { // 'gno 0.9' was never specified; just write 0.0. mod.SetGno(GnoVerDefault) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index bcd414b480c..b5cf27e11d6 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -82,6 +82,7 @@ func StoreWithOptions( panic(fmt.Errorf("test store preparing AST: %w", errs)) } } + m.Store.AddMemPackage(mpkg) return m.PreprocessFiles( mpkg.Name, mpkg.Path, From 18159fdc4b71f982c48357fa4eb5a604f308563a Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 12 May 2025 07:58:15 -0700 Subject: [PATCH 16/83] fix tests/files --- gnovm/tests/files/access1.gno | 4 +- gnovm/tests/files/access4.gno | 4 +- gnovm/tests/files/access6.gno | 4 +- gnovm/tests/files/access7.gno | 4 +- gnovm/tests/files/add3.gno | 4 +- gnovm/tests/files/addressable_10a_err.gno | 2 +- gnovm/tests/files/addressable_10b_err.gno | 2 +- gnovm/tests/files/addressable_1a_err.gno | 2 +- gnovm/tests/files/addressable_1b_err.gno | 2 +- gnovm/tests/files/addressable_1c_rrr.gno | 2 +- gnovm/tests/files/addressable_1d_err.gno | 2 +- gnovm/tests/files/addressable_2a_err.gno | 2 +- gnovm/tests/files/addressable_2b_err.gno | 2 +- gnovm/tests/files/addressable_3a_err.gno | 2 +- gnovm/tests/files/addressable_3b_err.gno | 2 +- gnovm/tests/files/addressable_3c_err.gno | 2 +- gnovm/tests/files/addressable_3d_err.gno | 2 +- gnovm/tests/files/addressable_4a_err.gno | 2 +- .../files/addressable_5a_err_stdlibs.gno | 2 +- .../files/addressable_5b_err_stdlibs.gno | 2 +- gnovm/tests/files/addressable_5c_err.gno | 2 +- gnovm/tests/files/addressable_5d_err.gno | 2 +- gnovm/tests/files/addressable_6a_err.gno | 2 +- gnovm/tests/files/addressable_6b_err.gno | 2 +- gnovm/tests/files/addressable_6c_err.gno | 2 +- gnovm/tests/files/addressable_6d_err.gno | 2 +- gnovm/tests/files/addressable_7a_err.gno | 4 +- gnovm/tests/files/addressable_7b_err.gno | 4 +- gnovm/tests/files/addressable_8a_err.gno | 2 +- gnovm/tests/files/addressable_9a_err.gno | 2 +- gnovm/tests/files/addressable_9b_err.gno | 2 +- gnovm/tests/files/alloc_0.gno | 4 +- gnovm/tests/files/alloc_1.gno | 4 +- gnovm/tests/files/alloc_2.gno | 2 +- gnovm/tests/files/alloc_3.gno | 4 +- gnovm/tests/files/alloc_4.gno | 4 +- gnovm/tests/files/alloc_5.gno | 4 +- gnovm/tests/files/alloc_6.gno | 4 +- gnovm/tests/files/alloc_6a.gno | 4 +- gnovm/tests/files/alloc_7.gno | 4 +- gnovm/tests/files/array3.gno | 2 +- gnovm/tests/files/array4.gno | 2 +- gnovm/tests/files/array5.gno | 2 +- gnovm/tests/files/assign11.gno | 4 +- gnovm/tests/files/assign12.gno | 4 +- gnovm/tests/files/assign22.gno | 4 +- gnovm/tests/files/assign23.gno | 4 +- gnovm/tests/files/assign24.gno | 4 +- gnovm/tests/files/assign25.gno | 4 +- gnovm/tests/files/assign25b.gno | 4 +- gnovm/tests/files/assign25c.gno | 4 +- gnovm/tests/files/assign25d.gno | 4 +- gnovm/tests/files/assign26.gno | 4 +- gnovm/tests/files/assign27.gno | 4 +- gnovm/tests/files/assign28.gno | 4 +- gnovm/tests/files/assign29.gno | 4 +- gnovm/tests/files/assign29_native.gno | 2 +- gnovm/tests/files/assign30.gno | 4 +- gnovm/tests/files/assign31.gno | 4 +- gnovm/tests/files/assign33.gno | 4 +- gnovm/tests/files/assign35.gno | 4 +- gnovm/tests/files/assign37.gno | 4 +- gnovm/tests/files/assign37b.gno | 4 +- gnovm/tests/files/assign38.gno | 4 +- .../append/named_unnamed_type2_filetest.gno | 5 +- .../method/declaredType6_filetest.gno | 5 +- .../method/declaredType6b_filetest.gno | 5 +- .../more/assgin_interface2_filetest.gno | 3 + .../more/assgin_two_filetest.gno | 5 +- .../more/errors2_filetest.gno | 3 + .../more/return_interface1_filetest.gno | 5 +- .../more/return_interface_filetest.gno | 5 +- .../unnamedtype0b_filetest.gno | 5 +- gnovm/tests/files/blankidentifier0.gno | 4 +- gnovm/tests/files/blankidentifier2.gno | 4 +- gnovm/tests/files/blankidentifier3.gno | 4 +- gnovm/tests/files/blankidentifier6.gno | 4 +- gnovm/tests/files/block2.gno | 2 +- gnovm/tests/files/bltn0.gno | 4 +- gnovm/tests/files/bool6.gno | 4 +- gnovm/tests/files/break0.gno | 4 +- gnovm/tests/files/cap10.gno | 2 +- gnovm/tests/files/cap7.gno | 2 +- gnovm/tests/files/cap8.gno | 2 +- gnovm/tests/files/cap9.gno | 2 +- gnovm/tests/files/circular_constant.gno | 4 +- gnovm/tests/files/closure.gno | 4 +- gnovm/tests/files/closure9.gno | 2 +- gnovm/tests/files/comp5.gno | 2 +- gnovm/tests/files/composite15.gno | 2 +- gnovm/tests/files/composite16.gno | 2 +- gnovm/tests/files/const23.gno | 4 +- gnovm/tests/files/const25.gno | 4 +- gnovm/tests/files/const26.gno | 4 +- gnovm/tests/files/const27.gno | 4 +- gnovm/tests/files/const28.gno | 4 +- gnovm/tests/files/const29.gno | 4 +- gnovm/tests/files/const30.gno | 4 +- gnovm/tests/files/const31.gno | 4 +- gnovm/tests/files/const32.gno | 4 +- gnovm/tests/files/const33.gno | 4 +- gnovm/tests/files/const34.gno | 4 +- gnovm/tests/files/const35.gno | 4 +- gnovm/tests/files/const36.gno | 4 +- gnovm/tests/files/const37_native.gno | 4 +- gnovm/tests/files/const37_stdlibs.gno | 4 +- gnovm/tests/files/const38.gno | 4 +- gnovm/tests/files/const39.gno | 4 +- gnovm/tests/files/const40.gno | 4 +- gnovm/tests/files/const41.gno | 4 +- gnovm/tests/files/const42.gno | 2 +- gnovm/tests/files/const43.gno | 4 +- gnovm/tests/files/const44.gno | 4 +- gnovm/tests/files/const45_b.gno | 4 +- gnovm/tests/files/const48.gno | 4 +- gnovm/tests/files/const49.gno | 2 +- gnovm/tests/files/const50.gno | 4 +- gnovm/tests/files/const55.gno | 4 +- gnovm/tests/files/const55a.gno | 4 +- gnovm/tests/files/const60.gno | 4 +- gnovm/tests/files/const61.gno | 4 +- gnovm/tests/files/const9.gno | 4 +- gnovm/tests/files/cont3.gno | 4 +- gnovm/tests/files/convert4.gno | 4 +- gnovm/tests/files/convert5.gno | 4 +- gnovm/tests/files/convert6.gno | 4 +- gnovm/tests/files/convert6a.gno | 4 +- gnovm/tests/files/convert6b.gno | 4 +- gnovm/tests/files/convert6c.gno | 4 +- gnovm/tests/files/convert6d.gno | 4 +- gnovm/tests/files/convert6e.gno | 4 +- gnovm/tests/files/convert7.gno | 4 +- gnovm/tests/files/convert7a.gno | 4 +- gnovm/tests/files/convert7b.gno | 4 +- gnovm/tests/files/defer0.gno | 2 +- gnovm/tests/files/float0.gno | 4 +- gnovm/tests/files/for20.gno | 2 +- gnovm/tests/files/for21.gno | 4 +- gnovm/tests/files/for22.gno | 4 +- gnovm/tests/files/for23.gno | 4 +- gnovm/tests/files/for24.gno | 4 +- gnovm/tests/files/for7.gno | 4 +- gnovm/tests/files/fun21.gno | 4 +- gnovm/tests/files/fun22.gno | 4 +- gnovm/tests/files/fun23.gno | 4 +- gnovm/tests/files/fun24.gno | 4 +- gnovm/tests/files/fun25.gno | 4 +- gnovm/tests/files/fun27.gno | 4 +- gnovm/tests/files/fun28.gno | 4 +- gnovm/tests/files/fun9.gno | 2 +- gnovm/tests/files/goto6.gno | 2 +- gnovm/tests/files/govdao/realm_govdao.gno | 20 +- gnovm/tests/files/if2.gno | 4 +- gnovm/tests/files/import10.gno | 4 +- gnovm/tests/files/import11.gno | 2 +- gnovm/tests/files/import12.gno | 2 +- gnovm/tests/files/import13.gno | 2 +- gnovm/tests/files/import13b.gno | 2 +- gnovm/tests/files/init1.gno | 4 +- gnovm/tests/files/interface47.gno | 4 +- gnovm/tests/files/invalid_labels0.gno | 2 +- gnovm/tests/files/invalid_labels1.gno | 4 +- gnovm/tests/files/invalid_labels2.gno | 4 +- gnovm/tests/files/invalid_labels3.gno | 4 +- gnovm/tests/files/issue_1096.gno | 2 +- gnovm/tests/files/len7.gno | 2 +- gnovm/tests/files/len8.gno | 2 +- gnovm/tests/files/map0.gno | 2 +- gnovm/tests/files/map1.gno | 2 +- gnovm/tests/files/native0.gno | 2 +- gnovm/tests/files/op7.gno | 4 +- gnovm/tests/files/overflow10.gno | 4 +- gnovm/tests/files/overflow11.gno | 4 +- gnovm/tests/files/overflow12.gno | 4 +- gnovm/tests/files/overflow13.gno | 4 +- gnovm/tests/files/overflow14.gno | 4 +- gnovm/tests/files/overflow16.gno | 4 +- gnovm/tests/files/overflow6.gno | 4 +- gnovm/tests/files/overflow7.gno | 4 +- gnovm/tests/files/overflow8.gno | 4 +- gnovm/tests/files/overflow9.gno | 4 +- gnovm/tests/files/panic0.gno | 2 +- gnovm/tests/files/panic0a.gno | 4 +- gnovm/tests/files/panic0b.gno | 10 +- gnovm/tests/files/panic0c.gno | 4 +- gnovm/tests/files/panic1.gno | 4 +- gnovm/tests/files/panic2a.gno | 256 +++++++++--------- gnovm/tests/files/panic2b.gno | 18 +- gnovm/tests/files/parse_err0.gno | 4 +- gnovm/tests/files/parse_err1.gno | 4 +- gnovm/tests/files/parse_err2.gno | 2 +- gnovm/tests/files/pkgname1.gno | 4 +- gnovm/tests/files/ptr10.gno | 4 +- gnovm/tests/files/ptr9.gno | 4 +- gnovm/tests/files/range8.gno | 4 +- gnovm/tests/files/recover10.gno | 2 +- gnovm/tests/files/recover13.gno | 2 +- gnovm/tests/files/recover16.gno | 2 +- gnovm/tests/files/recover1b.gno | 6 +- gnovm/tests/files/recover20.gno | 2 +- gnovm/tests/files/recover8.gno | 6 +- gnovm/tests/files/recursive1.gno | 4 +- gnovm/tests/files/recursive1c.gno | 4 +- gnovm/tests/files/recursive1d.gno | 4 +- gnovm/tests/files/recursive1e.gno | 2 +- gnovm/tests/files/recursive1f.gno | 4 +- gnovm/tests/files/recursive2.gno | 4 +- gnovm/tests/files/recursive2c.gno | 4 +- gnovm/tests/files/recursive4a.gno | 4 +- gnovm/tests/files/recursive5.gno | 4 +- gnovm/tests/files/recursive6a.gno | 4 +- gnovm/tests/files/recursive7a.gno | 4 +- gnovm/tests/files/recursive8.gno | 4 +- gnovm/tests/files/recursive9.gno | 4 +- gnovm/tests/files/recursive9a.gno | 4 +- gnovm/tests/files/recursive9b.gno | 4 +- gnovm/tests/files/recursive9c.gno | 4 +- gnovm/tests/files/recursive9d.gno | 4 +- gnovm/tests/files/redeclaration0.gno | 6 +- gnovm/tests/files/redeclaration1.gno | 6 +- gnovm/tests/files/redeclaration2.gno | 6 +- gnovm/tests/files/redeclaration3.gno | 6 +- gnovm/tests/files/redeclaration4.gno | 6 +- gnovm/tests/files/redeclaration5.gno | 6 +- gnovm/tests/files/redeclaration7.gno | 4 +- gnovm/tests/files/redeclaration9.gno | 4 +- gnovm/tests/files/redeclaration_global0.gno | 6 +- gnovm/tests/files/redeclaration_global1.gno | 6 +- gnovm/tests/files/redeclaration_global5.gno | 6 +- gnovm/tests/files/redefine6.gno | 4 +- gnovm/tests/files/slice2.gno | 2 +- gnovm/tests/files/slice3.gno | 4 +- gnovm/tests/files/slice4.gno | 2 +- gnovm/tests/files/struct2b.gno | 2 +- gnovm/tests/files/switch13.gno | 4 +- gnovm/tests/files/switch19.gno | 4 +- gnovm/tests/files/switch8.gno | 4 +- gnovm/tests/files/switch8b.gno | 4 +- gnovm/tests/files/switch8c.gno | 4 +- gnovm/tests/files/switch9.gno | 4 +- gnovm/tests/files/type30.gno | 4 +- gnovm/tests/files/type31.gno | 4 +- gnovm/tests/files/type32.gno | 4 +- gnovm/tests/files/type37.gno | 4 +- gnovm/tests/files/type37b.gno | 4 +- gnovm/tests/files/type37d.gno | 4 +- gnovm/tests/files/type37e.gno | 4 +- gnovm/tests/files/type37f.gno | 4 +- gnovm/tests/files/type39.gno | 4 +- gnovm/tests/files/type39a.gno | 4 +- gnovm/tests/files/type39b.gno | 4 +- gnovm/tests/files/type41.gno | 4 +- gnovm/tests/files/type42.gno | 4 +- gnovm/tests/files/typeassert1.gno | 2 +- gnovm/tests/files/typeassert2a.gno | 4 +- gnovm/tests/files/typeassert3.gno | 4 +- gnovm/tests/files/typeassert8.gno | 4 +- gnovm/tests/files/typeassert8a.gno | 4 +- gnovm/tests/files/typeassert9.gno | 2 +- gnovm/tests/files/typeassert9a.gno | 6 +- gnovm/tests/files/types/add_a0.gno | 4 +- gnovm/tests/files/types/add_a1.gno | 4 +- gnovm/tests/files/types/add_assign_a0.gno | 4 +- gnovm/tests/files/types/add_assign_a1.gno | 4 +- gnovm/tests/files/types/add_assign_a_01.gno | 4 +- gnovm/tests/files/types/add_assign_b0.gno | 4 +- gnovm/tests/files/types/add_assign_e0.gno | 4 +- gnovm/tests/files/types/add_assign_f0.gno | 4 +- gnovm/tests/files/types/add_assign_f1.gno | 4 +- gnovm/tests/files/types/add_assign_f2.gno | 4 +- gnovm/tests/files/types/add_assign_f3.gno | 4 +- gnovm/tests/files/types/add_b2.gno | 4 +- gnovm/tests/files/types/add_d4.gno | 4 +- gnovm/tests/files/types/add_e0.gno | 4 +- gnovm/tests/files/types/add_f0.gno | 4 +- gnovm/tests/files/types/add_f1.gno | 4 +- gnovm/tests/files/types/add_f2.gno | 4 +- gnovm/tests/files/types/and_a0.gno | 4 +- gnovm/tests/files/types/and_a1.gno | 4 +- gnovm/tests/files/types/and_b2.gno | 4 +- gnovm/tests/files/types/and_b3.gno | 4 +- gnovm/tests/files/types/and_d0.gno | 4 +- gnovm/tests/files/types/and_d4.gno | 4 +- gnovm/tests/files/types/and_e0.gno | 4 +- gnovm/tests/files/types/and_f0.gno | 4 +- gnovm/tests/files/types/and_f1.gno | 4 +- gnovm/tests/files/types/and_f2.gno | 4 +- gnovm/tests/files/types/assign_call.gno | 4 +- gnovm/tests/files/types/assign_index.gno | 4 +- gnovm/tests/files/types/assign_index_a.gno | 4 +- gnovm/tests/files/types/assign_index_b.gno | 4 +- gnovm/tests/files/types/assign_index_c.gno | 4 +- gnovm/tests/files/types/assign_literal.gno | 4 +- gnovm/tests/files/types/assign_literal10a.gno | 4 +- gnovm/tests/files/types/assign_literal11.gno | 4 +- gnovm/tests/files/types/assign_literal2.gno | 4 +- gnovm/tests/files/types/assign_literal2_a.gno | 4 +- gnovm/tests/files/types/assign_literal3.gno | 4 +- gnovm/tests/files/types/assign_literal4.gno | 4 +- gnovm/tests/files/types/assign_literal4_a.gno | 4 +- gnovm/tests/files/types/assign_literal5.gno | 4 +- gnovm/tests/files/types/assign_literal6.gno | 4 +- gnovm/tests/files/types/assign_literal7c.gno | 4 +- gnovm/tests/files/types/assign_literal_a.gno | 4 +- gnovm/tests/files/types/assign_nil.gno | 4 +- gnovm/tests/files/types/assign_nil2.gno | 4 +- gnovm/tests/files/types/assign_range_a.gno | 4 +- gnovm/tests/files/types/assign_range_a1.gno | 4 +- gnovm/tests/files/types/assign_range_b.gno | 4 +- gnovm/tests/files/types/assign_range_b1.gno | 4 +- gnovm/tests/files/types/assign_range_c.gno | 4 +- gnovm/tests/files/types/assign_range_d.gno | 4 +- gnovm/tests/files/types/assign_range_e.gno | 4 +- gnovm/tests/files/types/assign_rune_a.gno | 4 +- .../files/types/assign_type_assertion.gno | 4 +- .../files/types/assign_type_assertion_b.gno | 4 +- .../files/types/assign_type_assertion_c.gno | 4 +- .../files/types/assign_type_assertion_d.gno | 4 +- .../files/types/assign_type_assertion_e.gno | 4 +- .../files/types/assign_type_assertion_f.gno | 4 +- .../files/types/assign_type_assertion_g.gno | 4 +- gnovm/tests/files/types/bigdec2.gno | 4 +- gnovm/tests/files/types/bigdec5.gno | 4 +- gnovm/tests/files/types/bigdec_6.gno | 4 +- gnovm/tests/files/types/cmp_array_b.gno | 4 +- gnovm/tests/files/types/cmp_array_c.gno | 4 +- gnovm/tests/files/types/cmp_iface_5.gno | 4 +- .../tests/files/types/cmp_iface_5_stdlibs.gno | 4 +- gnovm/tests/files/types/cmp_pointer.gno | 4 +- gnovm/tests/files/types/cmp_primitive_1.gno | 4 +- gnovm/tests/files/types/cmp_slice_4.gno | 4 +- gnovm/tests/files/types/cmp_struct_a.gno | 4 +- gnovm/tests/files/types/cmp_struct_b.gno | 4 +- gnovm/tests/files/types/cmp_struct_c.gno | 4 +- gnovm/tests/files/types/cmp_struct_c1.gno | 4 +- gnovm/tests/files/types/cmp_struct_d.gno | 4 +- gnovm/tests/files/types/cmp_struct_e.gno | 4 +- gnovm/tests/files/types/cmp_struct_g.gno | 4 +- gnovm/tests/files/types/eql_0a0.gno | 4 +- gnovm/tests/files/types/eql_0a01.gno | 4 +- gnovm/tests/files/types/eql_0a02.gno | 4 +- gnovm/tests/files/types/eql_0a03.gno | 4 +- gnovm/tests/files/types/eql_0a1.gno | 4 +- gnovm/tests/files/types/eql_0a1a0.gno | 4 +- gnovm/tests/files/types/eql_0a1a1.gno | 4 +- gnovm/tests/files/types/eql_0a1f.gno | 4 +- gnovm/tests/files/types/eql_0a1g.gno | 4 +- gnovm/tests/files/types/eql_0a2.gno | 4 +- gnovm/tests/files/types/eql_0a3.gno | 4 +- gnovm/tests/files/types/eql_0a4.gno | 4 +- gnovm/tests/files/types/eql_0b2.gno | 4 +- gnovm/tests/files/types/eql_0b4.gno | 4 +- gnovm/tests/files/types/eql_0c2.gno | 4 +- gnovm/tests/files/types/eql_0e0.gno | 4 +- gnovm/tests/files/types/eql_0e1.gno | 4 +- gnovm/tests/files/types/eql_0f0.gno | 4 +- gnovm/tests/files/types/eql_0f1.gno | 4 +- gnovm/tests/files/types/eql_0f14.gno | 4 +- gnovm/tests/files/types/eql_0f16.gno | 4 +- gnovm/tests/files/types/eql_0f17.gno | 4 +- gnovm/tests/files/types/eql_0f20.gno | 4 +- gnovm/tests/files/types/eql_0f21.gno | 4 +- gnovm/tests/files/types/eql_0f27.gno | 4 +- gnovm/tests/files/types/eql_0f28.gno | 4 +- gnovm/tests/files/types/eql_0f29.gno | 4 +- gnovm/tests/files/types/eql_0f2b.gno | 4 +- gnovm/tests/files/types/eql_0f2c.gno | 4 +- gnovm/tests/files/types/eql_0f30.gno | 4 +- gnovm/tests/files/types/eql_0f30a.gno | 4 +- gnovm/tests/files/types/eql_0f30b.gno | 4 +- gnovm/tests/files/types/eql_0f30d.gno | 4 +- gnovm/tests/files/types/eql_0f30f.gno | 4 +- gnovm/tests/files/types/eql_0f30g.gno | 4 +- gnovm/tests/files/types/eql_0f41.gno | 4 +- gnovm/tests/files/types/eql_0f8.gno | 4 +- .../files/types/explicit_conversion_1.gno | 4 +- gnovm/tests/files/types/incdec_a1.gno | 4 +- gnovm/tests/files/types/incdec_a4.gno | 4 +- gnovm/tests/files/types/nil.gno | 4 +- gnovm/tests/files/types/or_a0.gno | 4 +- gnovm/tests/files/types/or_a1.gno | 4 +- gnovm/tests/files/types/or_b2.gno | 4 +- gnovm/tests/files/types/or_b3.gno | 4 +- gnovm/tests/files/types/or_d0.gno | 4 +- gnovm/tests/files/types/or_d4.gno | 4 +- gnovm/tests/files/types/or_e0.gno | 4 +- gnovm/tests/files/types/or_f0.gno | 4 +- gnovm/tests/files/types/or_f1.gno | 4 +- gnovm/tests/files/types/or_f2.gno | 4 +- gnovm/tests/files/types/overflow_a1.gno | 2 +- gnovm/tests/files/types/rem_a0.gno | 4 +- gnovm/tests/files/types/rem_a1.gno | 4 +- gnovm/tests/files/types/rem_a2.gno | 4 +- gnovm/tests/files/types/rem_f3.gno | 4 +- gnovm/tests/files/types/runtime_a0.gno | 4 +- gnovm/tests/files/types/runtime_a3.gno | 4 +- gnovm/tests/files/types/shift_a11.gno | 4 +- gnovm/tests/files/types/shift_a14.gno | 4 +- gnovm/tests/files/types/shift_a15.gno | 4 +- gnovm/tests/files/types/shift_a16.gno | 4 +- gnovm/tests/files/types/shift_a3.gno | 4 +- gnovm/tests/files/types/shift_a7.gno | 4 +- gnovm/tests/files/types/shift_b6.gno | 4 +- gnovm/tests/files/types/shift_b7.gno | 4 +- gnovm/tests/files/types/shift_c6.gno | 4 +- gnovm/tests/files/types/shift_c7.gno | 4 +- gnovm/tests/files/types/shift_c8.gno | 4 +- gnovm/tests/files/types/shift_d12.gno | 4 +- gnovm/tests/files/types/shift_d13.gno | 4 +- gnovm/tests/files/types/shift_d27.gno | 4 +- gnovm/tests/files/types/shift_d28.gno | 4 +- gnovm/tests/files/types/shift_d32a.gno | 4 +- gnovm/tests/files/types/shift_d34.gno | 4 +- gnovm/tests/files/types/shift_d37.gno | 4 +- gnovm/tests/files/types/shift_d38.gno | 4 +- gnovm/tests/files/types/shift_d4.gno | 4 +- gnovm/tests/files/types/shift_d40.gno | 4 +- gnovm/tests/files/types/shift_d41.gno | 4 +- gnovm/tests/files/types/shift_d44.gno | 4 +- gnovm/tests/files/types/shift_d4a.gno | 4 +- gnovm/tests/files/types/shift_d5.gno | 4 +- gnovm/tests/files/types/shift_d50.gno | 4 +- gnovm/tests/files/types/shift_d51.gno | 4 +- gnovm/tests/files/types/shift_d54.gno | 4 +- gnovm/tests/files/types/shift_d56.gno | 4 +- gnovm/tests/files/types/shift_d5b.gno | 4 +- gnovm/tests/files/types/shift_e0.gno | 4 +- gnovm/tests/files/types/shift_e1.gno | 4 +- gnovm/tests/files/types/shift_e2.gno | 4 +- gnovm/tests/files/types/shift_e3.gno | 4 +- gnovm/tests/files/types/shift_e4.gno | 4 +- gnovm/tests/files/types/shift_e7.gno | 4 +- gnovm/tests/files/types/shift_e7a.gno | 4 +- gnovm/tests/files/types/shift_e7b.gno | 4 +- gnovm/tests/files/types/shift_e8.gno | 4 +- gnovm/tests/files/types/shift_f1b.gno | 4 +- gnovm/tests/files/types/shift_f2.gno | 4 +- gnovm/tests/files/types/shift_f2a.gno | 4 +- gnovm/tests/files/types/shift_f2b.gno | 4 +- gnovm/tests/files/types/shift_f2c.gno | 4 +- gnovm/tests/files/types/shift_f2d.gno | 4 +- gnovm/tests/files/types/shift_f3.gno | 4 +- gnovm/tests/files/types/shift_f3a.gno | 4 +- gnovm/tests/files/types/shift_f3b.gno | 4 +- gnovm/tests/files/types/shift_f3c.gno | 4 +- gnovm/tests/files/types/typed_nil_a.gno | 4 +- gnovm/tests/files/types/unary_a0c.gno | 4 +- gnovm/tests/files/types/unary_a2a.gno | 4 +- gnovm/tests/files/types/unary_a6.gno | 4 +- gnovm/tests/files/var18.gno | 4 +- gnovm/tests/files/var19.gno | 4 +- gnovm/tests/files/var20.gno | 4 +- gnovm/tests/files/var21.gno | 4 +- gnovm/tests/files/var22.gno | 4 +- gnovm/tests/files/var22b.gno | 4 +- gnovm/tests/files/var22c.gno | 4 +- gnovm/tests/files/var23.gno | 4 +- gnovm/tests/files/var24.gno | 4 +- gnovm/tests/files/var25.gno | 4 +- gnovm/tests/files/var26.gno | 4 +- gnovm/tests/files/var27.gno | 2 +- gnovm/tests/files/var31.gno | 4 +- gnovm/tests/files/var32.gno | 4 +- gnovm/tests/files/var33.gno | 2 +- gnovm/tests/files/var34.gno | 4 +- gnovm/tests/files/var34b.gno | 4 +- gnovm/tests/files/var34c.gno | 4 +- gnovm/tests/files/var35.gno | 4 +- gnovm/tests/files/zrealm_crossrealm22.gno | 38 ++- gnovm/tests/files/zrealm_crossrealm28.gno | 2 +- gnovm/tests/files/zrealm_natbind0.gno | 10 +- gnovm/tests/files/zrealm_panic.gno | 4 +- gnovm/tests/integ/init/gno.mod | 2 + 473 files changed, 1068 insertions(+), 1037 deletions(-) diff --git a/gnovm/tests/files/access1.gno b/gnovm/tests/files/access1.gno index b5d28727386..f6df8007a66 100644 --- a/gnovm/tests/files/access1.gno +++ b/gnovm/tests/files/access1.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/access1.gno:8:10: cannot access gno.land/p/demo/testutils.testVar2 from main +// main/access1.gno:8:10: cannot access gno.land/p/demo/testutils.testVar2 from main // TypeCheckError: -// main/files/access1.gno:8:20: name testVar2 not exported by package testutils +// main/access1.gno:8:20: name testVar2 not exported by package testutils diff --git a/gnovm/tests/files/access4.gno b/gnovm/tests/files/access4.gno index 99ba4f1daeb..bf328793835 100644 --- a/gnovm/tests/files/access4.gno +++ b/gnovm/tests/files/access4.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/access4.gno:9:10: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main +// main/access4.gno:9:10: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main // TypeCheckError: -// main/files/access4.gno:9:12: x.privateField undefined (cannot refer to unexported field privateField) +// main/access4.gno:9:12: x.privateField undefined (cannot refer to unexported field privateField) diff --git a/gnovm/tests/files/access6.gno b/gnovm/tests/files/access6.gno index 54521096e6d..07d816dcd13 100644 --- a/gnovm/tests/files/access6.gno +++ b/gnovm/tests/files/access6.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/access6.gno:15:2: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) +// main/access6.gno:15:2: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) // TypeCheckError: -// main/files/access6.gno:15:34: cannot use x (variable of struct type mystruct) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: mystruct does not implement testutils.PrivateInterface (unexported method privateMethod) +// main/access6.gno:15:34: cannot use x (variable of struct type mystruct) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: mystruct does not implement testutils.PrivateInterface (unexported method privateMethod) diff --git a/gnovm/tests/files/access7.gno b/gnovm/tests/files/access7.gno index 4e4d6edc312..e8cfb32a4e8 100644 --- a/gnovm/tests/files/access7.gno +++ b/gnovm/tests/files/access7.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/access7.gno:19:2: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) +// main/access7.gno:19:2: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) // TypeCheckError: -// main/files/access7.gno:19:34: cannot use x (variable of interface type PrivateInterface2) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: PrivateInterface2 does not implement testutils.PrivateInterface (missing method privateMethod) +// main/access7.gno:19:34: cannot use x (variable of interface type PrivateInterface2) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: PrivateInterface2 does not implement testutils.PrivateInterface (missing method privateMethod) diff --git a/gnovm/tests/files/add3.gno b/gnovm/tests/files/add3.gno index bb2645a3e09..9dd7aeef4be 100644 --- a/gnovm/tests/files/add3.gno +++ b/gnovm/tests/files/add3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/add3.gno:5:7: invalid operation: a + (const (undefined)) (mismatched types int and untyped nil) +// main/add3.gno:5:7: invalid operation: a + (const (undefined)) (mismatched types int and untyped nil) // TypeCheckError: -// main/files/add3.gno:5:7: invalid operation: a + nil (mismatched types int and untyped nil); main/files/add3.gno:5:2: declared and not used: i +// main/add3.gno:5:7: invalid operation: a + nil (mismatched types int and untyped nil); main/add3.gno:5:2: declared and not used: i diff --git a/gnovm/tests/files/addressable_10a_err.gno b/gnovm/tests/files/addressable_10a_err.gno index 29bd99016d6..27e74c68b0e 100644 --- a/gnovm/tests/files/addressable_10a_err.gno +++ b/gnovm/tests/files/addressable_10a_err.gno @@ -14,4 +14,4 @@ func getPtr() *S { // illegal assignment X expression type *gnolang.CallExpr // TypeCheckError: -// main/files/addressable_10a_err.gno:4:11: invalid operation: cannot take address of getPtr() (value of type *S) +// main/addressable_10a_err.gno:4:11: invalid operation: cannot take address of getPtr() (value of type *S) diff --git a/gnovm/tests/files/addressable_10b_err.gno b/gnovm/tests/files/addressable_10b_err.gno index 1007db5404c..ef8d28dbe45 100644 --- a/gnovm/tests/files/addressable_10b_err.gno +++ b/gnovm/tests/files/addressable_10b_err.gno @@ -12,4 +12,4 @@ func main() { // illegal assignment X expression type *gnolang.CallExpr // TypeCheckError: -// main/files/addressable_10b_err.gno:8:11: invalid operation: cannot take address of new(S) (value of type *S) +// main/addressable_10b_err.gno:8:11: invalid operation: cannot take address of new(S) (value of type *S) diff --git a/gnovm/tests/files/addressable_1a_err.gno b/gnovm/tests/files/addressable_1a_err.gno index ff52cc5d5c4..e1c2066680d 100644 --- a/gnovm/tests/files/addressable_1a_err.gno +++ b/gnovm/tests/files/addressable_1a_err.gno @@ -5,4 +5,4 @@ func main() { } // TypeCheckError: -// main/files/addressable_1a_err.gno:4:7: invalid operation: cannot take address of [1]int{…}[0] (value of type int) +// main/addressable_1a_err.gno:4:7: invalid operation: cannot take address of [1]int{…}[0] (value of type int) diff --git a/gnovm/tests/files/addressable_1b_err.gno b/gnovm/tests/files/addressable_1b_err.gno index b625f553117..279c68d0ac8 100644 --- a/gnovm/tests/files/addressable_1b_err.gno +++ b/gnovm/tests/files/addressable_1b_err.gno @@ -5,4 +5,4 @@ func main() { } // TypeCheckError: -// main/files/addressable_1b_err.gno:4:6: invalid operation: cannot slice [1]int{…} (value of type [1]int) (value not addressable) +// main/addressable_1b_err.gno:4:6: invalid operation: cannot slice [1]int{…} (value of type [1]int) (value not addressable) diff --git a/gnovm/tests/files/addressable_1c_rrr.gno b/gnovm/tests/files/addressable_1c_rrr.gno index fd22e3f2276..c089bed4bef 100644 --- a/gnovm/tests/files/addressable_1c_rrr.gno +++ b/gnovm/tests/files/addressable_1c_rrr.gno @@ -10,4 +10,4 @@ func getArr() [1]int { } // TypeCheckError: -// main/files/addressable_1c_rrr.gno:4:7: invalid operation: cannot take address of getArr()[0] (value of type int) +// main/addressable_1c_rrr.gno:4:7: invalid operation: cannot take address of getArr()[0] (value of type int) diff --git a/gnovm/tests/files/addressable_1d_err.gno b/gnovm/tests/files/addressable_1d_err.gno index be3c2b380a1..30b5005b770 100644 --- a/gnovm/tests/files/addressable_1d_err.gno +++ b/gnovm/tests/files/addressable_1d_err.gno @@ -9,4 +9,4 @@ func getArr() [1]int { } // TypeCheckError: -// main/files/addressable_1d_err.gno:4:6: invalid operation: cannot slice getArr() (value of type [1]int) (value not addressable) +// main/addressable_1d_err.gno:4:6: invalid operation: cannot slice getArr() (value of type [1]int) (value not addressable) diff --git a/gnovm/tests/files/addressable_2a_err.gno b/gnovm/tests/files/addressable_2a_err.gno index e27187f36df..61694ec202a 100644 --- a/gnovm/tests/files/addressable_2a_err.gno +++ b/gnovm/tests/files/addressable_2a_err.gno @@ -8,4 +8,4 @@ func main() { // illegal assignment X expression type *gnolang.SliceExpr // TypeCheckError: -// main/files/addressable_2a_err.gno:4:7: invalid operation: cannot take address of []int{…}[:] (value of type []int) +// main/addressable_2a_err.gno:4:7: invalid operation: cannot take address of []int{…}[:] (value of type []int) diff --git a/gnovm/tests/files/addressable_2b_err.gno b/gnovm/tests/files/addressable_2b_err.gno index 6bd40b83881..e7af94aa4ec 100644 --- a/gnovm/tests/files/addressable_2b_err.gno +++ b/gnovm/tests/files/addressable_2b_err.gno @@ -12,4 +12,4 @@ func getSlice() []int { // illegal assignment X expression type *gnolang.CallExpr // TypeCheckError: -// main/files/addressable_2b_err.gno:4:7: invalid operation: cannot take address of getSlice() (value of type []int) +// main/addressable_2b_err.gno:4:7: invalid operation: cannot take address of getSlice() (value of type []int) diff --git a/gnovm/tests/files/addressable_3a_err.gno b/gnovm/tests/files/addressable_3a_err.gno index 70a83dbe9ba..743c2453ea9 100644 --- a/gnovm/tests/files/addressable_3a_err.gno +++ b/gnovm/tests/files/addressable_3a_err.gno @@ -11,4 +11,4 @@ func main() { } // TypeCheckError: -// main/files/addressable_3a_err.gno:10:7: invalid operation: cannot take address of S{…}.i (value of type int) +// main/addressable_3a_err.gno:10:7: invalid operation: cannot take address of S{…}.i (value of type int) diff --git a/gnovm/tests/files/addressable_3b_err.gno b/gnovm/tests/files/addressable_3b_err.gno index 3b15a86efae..1cf2a37c3c3 100644 --- a/gnovm/tests/files/addressable_3b_err.gno +++ b/gnovm/tests/files/addressable_3b_err.gno @@ -13,4 +13,4 @@ func getStruct() S { } // TypeCheckError: -// main/files/addressable_3b_err.gno:8:7: invalid operation: cannot take address of getStruct().i (value of type int) +// main/addressable_3b_err.gno:8:7: invalid operation: cannot take address of getStruct().i (value of type int) diff --git a/gnovm/tests/files/addressable_3c_err.gno b/gnovm/tests/files/addressable_3c_err.gno index 637876386ae..8a446b952be 100644 --- a/gnovm/tests/files/addressable_3c_err.gno +++ b/gnovm/tests/files/addressable_3c_err.gno @@ -14,4 +14,4 @@ func main() { } // TypeCheckError: -// main/files/addressable_3c_err.gno:13:7: invalid operation: cannot take address of makeT().Mp (value of type *int) +// main/addressable_3c_err.gno:13:7: invalid operation: cannot take address of makeT().Mp (value of type *int) diff --git a/gnovm/tests/files/addressable_3d_err.gno b/gnovm/tests/files/addressable_3d_err.gno index 28eadef7a5a..bed727d9bcb 100644 --- a/gnovm/tests/files/addressable_3d_err.gno +++ b/gnovm/tests/files/addressable_3d_err.gno @@ -8,4 +8,4 @@ func main() { // illegal assignment X expression type *gnolang.RefExpr // TypeCheckError: -// main/files/addressable_3d_err.gno:4:7: invalid operation: cannot take address of (&struct{}{}) (value of type *struct{}) +// main/addressable_3d_err.gno:4:7: invalid operation: cannot take address of (&struct{}{}) (value of type *struct{}) diff --git a/gnovm/tests/files/addressable_4a_err.gno b/gnovm/tests/files/addressable_4a_err.gno index e088329c7eb..99ac914b8c6 100644 --- a/gnovm/tests/files/addressable_4a_err.gno +++ b/gnovm/tests/files/addressable_4a_err.gno @@ -6,4 +6,4 @@ func main() { } // TypeCheckError: -// main/files/addressable_4a_err.gno:5:7: invalid operation: cannot take address of greeting[2] (value of type byte) +// main/addressable_4a_err.gno:5:7: invalid operation: cannot take address of greeting[2] (value of type byte) diff --git a/gnovm/tests/files/addressable_5a_err_stdlibs.gno b/gnovm/tests/files/addressable_5a_err_stdlibs.gno index 7e6d1fc3f6e..1ff59bc38d1 100644 --- a/gnovm/tests/files/addressable_5a_err_stdlibs.gno +++ b/gnovm/tests/files/addressable_5a_err_stdlibs.gno @@ -11,4 +11,4 @@ func main() { // illegal assignment X expression type *gnolang.ConstExpr // TypeCheckError: -// main/files/addressable_5a_err_stdlibs.gno:7:7: invalid operation: cannot take address of math.MaxUint8 (untyped int constant 255) +// main/addressable_5a_err_stdlibs.gno:7:7: invalid operation: cannot take address of math.MaxUint8 (untyped int constant 255) diff --git a/gnovm/tests/files/addressable_5b_err_stdlibs.gno b/gnovm/tests/files/addressable_5b_err_stdlibs.gno index 1a50fb98c08..2cedc365020 100644 --- a/gnovm/tests/files/addressable_5b_err_stdlibs.gno +++ b/gnovm/tests/files/addressable_5b_err_stdlibs.gno @@ -11,4 +11,4 @@ func main() { // illegal assignment X expression type *gnolang.ConstExpr // TypeCheckError: -// main/files/addressable_5b_err_stdlibs.gno:7:7: invalid operation: cannot take address of std.BankerTypeReadonly (constant 0 of uint8 type std.BankerType) +// main/addressable_5b_err_stdlibs.gno:7:7: invalid operation: cannot take address of std.BankerTypeReadonly (constant 0 of uint8 type std.BankerType) diff --git a/gnovm/tests/files/addressable_5c_err.gno b/gnovm/tests/files/addressable_5c_err.gno index 37c541c30ac..00c7443edf5 100644 --- a/gnovm/tests/files/addressable_5c_err.gno +++ b/gnovm/tests/files/addressable_5c_err.gno @@ -10,4 +10,4 @@ func main() { // illegal assignment X expression type *gnolang.ConstExpr // TypeCheckError: -// main/files/addressable_5c_err.gno:6:7: invalid operation: cannot take address of a (untyped int constant 1) +// main/addressable_5c_err.gno:6:7: invalid operation: cannot take address of a (untyped int constant 1) diff --git a/gnovm/tests/files/addressable_5d_err.gno b/gnovm/tests/files/addressable_5d_err.gno index d854c01fb86..8c312369499 100644 --- a/gnovm/tests/files/addressable_5d_err.gno +++ b/gnovm/tests/files/addressable_5d_err.gno @@ -10,4 +10,4 @@ func main() { // illegal assignment X expression type *gnolang.ConstExpr // TypeCheckError: -// main/files/addressable_5d_err.gno:6:7: invalid operation: cannot take address of a (constant 1 of type int) +// main/addressable_5d_err.gno:6:7: invalid operation: cannot take address of a (constant 1 of type int) diff --git a/gnovm/tests/files/addressable_6a_err.gno b/gnovm/tests/files/addressable_6a_err.gno index c7b13c3b49e..22a184296cf 100644 --- a/gnovm/tests/files/addressable_6a_err.gno +++ b/gnovm/tests/files/addressable_6a_err.gno @@ -10,4 +10,4 @@ func main() { // illegal assignment X expression type *gnolang.TypeAssertExpr // TypeCheckError: -// main/files/addressable_6a_err.gno:6:11: invalid operation: cannot take address of i.(int) (comma, ok expression of type int) +// main/addressable_6a_err.gno:6:11: invalid operation: cannot take address of i.(int) (comma, ok expression of type int) diff --git a/gnovm/tests/files/addressable_6b_err.gno b/gnovm/tests/files/addressable_6b_err.gno index e75515b98f7..96e8a452086 100644 --- a/gnovm/tests/files/addressable_6b_err.gno +++ b/gnovm/tests/files/addressable_6b_err.gno @@ -14,4 +14,4 @@ func main() { // &(9 int) // TypeCheckError: -// main/files/addressable_6b_err.gno:10:11: invalid operation: cannot take address of i.(S).a (value of type int) +// main/addressable_6b_err.gno:10:11: invalid operation: cannot take address of i.(S).a (value of type int) diff --git a/gnovm/tests/files/addressable_6c_err.gno b/gnovm/tests/files/addressable_6c_err.gno index 27c9ea2e21f..addd7fcc09a 100644 --- a/gnovm/tests/files/addressable_6c_err.gno +++ b/gnovm/tests/files/addressable_6c_err.gno @@ -10,4 +10,4 @@ func main() { // &(1 int) // TypeCheckError: -// main/files/addressable_6c_err.gno:6:11: invalid operation: cannot take address of i.([1]int)[0] (value of type int) +// main/addressable_6c_err.gno:6:11: invalid operation: cannot take address of i.([1]int)[0] (value of type int) diff --git a/gnovm/tests/files/addressable_6d_err.gno b/gnovm/tests/files/addressable_6d_err.gno index 1342e4341ed..ab6d763cdc5 100644 --- a/gnovm/tests/files/addressable_6d_err.gno +++ b/gnovm/tests/files/addressable_6d_err.gno @@ -12,4 +12,4 @@ func getSlice() any { // illegal assignment X expression type *gnolang.TypeAssertExpr // TypeCheckError: -// main/files/addressable_6d_err.gno:4:7: invalid operation: cannot take address of getSlice().([]int) (comma, ok expression of type []int) +// main/addressable_6d_err.gno:4:7: invalid operation: cannot take address of getSlice().([]int) (comma, ok expression of type []int) diff --git a/gnovm/tests/files/addressable_7a_err.gno b/gnovm/tests/files/addressable_7a_err.gno index 2af4bad7a80..fe3f15e45c1 100644 --- a/gnovm/tests/files/addressable_7a_err.gno +++ b/gnovm/tests/files/addressable_7a_err.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/addressable_7a_err.gno:8:2: getTypeOf() only supports *CallExpr with 1 result, got ([]int,[]string) +// main/addressable_7a_err.gno:8:2: getTypeOf() only supports *CallExpr with 1 result, got ([]int,[]string) // TypeCheckError: -// main/files/addressable_7a_err.gno:8:7: multiple-value foo() (value of type ([]int, []string)) in single-value context +// main/addressable_7a_err.gno:8:7: multiple-value foo() (value of type ([]int, []string)) in single-value context diff --git a/gnovm/tests/files/addressable_7b_err.gno b/gnovm/tests/files/addressable_7b_err.gno index c86f65127dc..71beaa89a95 100644 --- a/gnovm/tests/files/addressable_7b_err.gno +++ b/gnovm/tests/files/addressable_7b_err.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/addressable_7b_err.gno:4:2: RHS should not be &((const (9 int))) when len(Lhs) > len(Rhs) +// main/addressable_7b_err.gno:4:2: RHS should not be &((const (9 int))) when len(Lhs) > len(Rhs) // TypeCheckError: -// main/files/addressable_7b_err.gno:4:10: invalid operation: cannot take address of int(9) (constant 9 of type int) +// main/addressable_7b_err.gno:4:10: invalid operation: cannot take address of int(9) (constant 9 of type int) diff --git a/gnovm/tests/files/addressable_8a_err.gno b/gnovm/tests/files/addressable_8a_err.gno index 61be68ee8aa..fd5e1e23ef7 100644 --- a/gnovm/tests/files/addressable_8a_err.gno +++ b/gnovm/tests/files/addressable_8a_err.gno @@ -8,4 +8,4 @@ func main() { // illegal assignment X expression type *gnolang.FuncLitExpr // TypeCheckError: -// main/files/addressable_8a_err.gno:4:7: invalid operation: cannot take address of (func() literal) (value of type func()) +// main/addressable_8a_err.gno:4:7: invalid operation: cannot take address of (func() literal) (value of type func()) diff --git a/gnovm/tests/files/addressable_9a_err.gno b/gnovm/tests/files/addressable_9a_err.gno index dc2af72c314..321371a641f 100644 --- a/gnovm/tests/files/addressable_9a_err.gno +++ b/gnovm/tests/files/addressable_9a_err.gno @@ -10,4 +10,4 @@ func main() { // &(5 int) // TypeCheckError: -// main/files/addressable_9a_err.gno:6:11: invalid operation: cannot take address of m[4] (map index expression of type int) +// main/addressable_9a_err.gno:6:11: invalid operation: cannot take address of m[4] (map index expression of type int) diff --git a/gnovm/tests/files/addressable_9b_err.gno b/gnovm/tests/files/addressable_9b_err.gno index e8b8bad51ef..bccd3b2a035 100644 --- a/gnovm/tests/files/addressable_9b_err.gno +++ b/gnovm/tests/files/addressable_9b_err.gno @@ -15,4 +15,4 @@ func main() { // &(7 int) // TypeCheckError: -// main/files/addressable_9b_err.gno:11:11: invalid operation: cannot take address of mmm[3][3].i (value of type int) +// main/addressable_9b_err.gno:11:11: invalid operation: cannot take address of mmm[3][3].i (value of type int) diff --git a/gnovm/tests/files/alloc_0.gno b/gnovm/tests/files/alloc_0.gno index 5b3fb2662b7..29ba33d6b5f 100644 --- a/gnovm/tests/files/alloc_0.gno +++ b/gnovm/tests/files/alloc_0.gno @@ -16,7 +16,7 @@ func main() { } // Output: -// MemStats: Allocator{maxBytes:100000000, bytes:6358} +// MemStats: Allocator{maxBytes:100000000, bytes:6346} // TypeCheckError: -// main/files/alloc_0.gno:13:2: declared and not used: f1 +// main/alloc_0.gno:13:2: declared and not used: f1 diff --git a/gnovm/tests/files/alloc_1.gno b/gnovm/tests/files/alloc_1.gno index 90f6d1b7824..fe78d98c8ce 100644 --- a/gnovm/tests/files/alloc_1.gno +++ b/gnovm/tests/files/alloc_1.gno @@ -21,7 +21,7 @@ func main() { } // Output: -// MemStats: Allocator{maxBytes:100000000, bytes:7608} +// MemStats: Allocator{maxBytes:100000000, bytes:7596} // TypeCheckError: -// main/files/alloc_1.gno:18:2: declared and not used: S1 +// main/alloc_1.gno:18:2: declared and not used: S1 diff --git a/gnovm/tests/files/alloc_2.gno b/gnovm/tests/files/alloc_2.gno index c2edc5e50f8..ce035e8418c 100644 --- a/gnovm/tests/files/alloc_2.gno +++ b/gnovm/tests/files/alloc_2.gno @@ -13,4 +13,4 @@ func main() { // allocation limit exceeded // TypeCheckError: -// main/files/alloc_2.gno:8:2: declared and not used: data +// main/alloc_2.gno:8:2: declared and not used: data diff --git a/gnovm/tests/files/alloc_3.gno b/gnovm/tests/files/alloc_3.gno index 473bdd17b0d..49e8c4518bd 100644 --- a/gnovm/tests/files/alloc_3.gno +++ b/gnovm/tests/files/alloc_3.gno @@ -11,7 +11,7 @@ func main() { } // Output: -// MemStats after GC: Allocator{maxBytes:110000000, bytes:5704} +// MemStats after GC: Allocator{maxBytes:110000000, bytes:5692} // TypeCheckError: -// main/files/alloc_3.gno:7:2: declared and not used: data +// main/alloc_3.gno:7:2: declared and not used: data diff --git a/gnovm/tests/files/alloc_4.gno b/gnovm/tests/files/alloc_4.gno index c6abcb497f6..51181950db4 100644 --- a/gnovm/tests/files/alloc_4.gno +++ b/gnovm/tests/files/alloc_4.gno @@ -22,5 +22,5 @@ func main() { } // Output: -// memstats in main after first GC: Allocator{maxBytes:50000, bytes:11438} -// memstats in main after second GC: Allocator{maxBytes:50000, bytes:7069} +// memstats in main after first GC: Allocator{maxBytes:50000, bytes:11426} +// memstats in main after second GC: Allocator{maxBytes:50000, bytes:7057} diff --git a/gnovm/tests/files/alloc_5.gno b/gnovm/tests/files/alloc_5.gno index 06689499924..f7ad6b147c1 100644 --- a/gnovm/tests/files/alloc_5.gno +++ b/gnovm/tests/files/alloc_5.gno @@ -19,7 +19,7 @@ func main() { } // Output: -// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6048} +// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6036} // TypeCheckError: -// main/files/alloc_5.gno:7:2: declared and not used: data +// main/alloc_5.gno:7:2: declared and not used: data diff --git a/gnovm/tests/files/alloc_6.gno b/gnovm/tests/files/alloc_6.gno index 8ed11220473..a23f86cce96 100644 --- a/gnovm/tests/files/alloc_6.gno +++ b/gnovm/tests/files/alloc_6.gno @@ -13,7 +13,7 @@ func main() { } // Output: -// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6048} +// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6036} // TypeCheckError: -// main/files/alloc_6.gno:7:6: declared and not used: a +// main/alloc_6.gno:7:6: declared and not used: a diff --git a/gnovm/tests/files/alloc_6a.gno b/gnovm/tests/files/alloc_6a.gno index aa34b938bc6..d2e76b6bd56 100644 --- a/gnovm/tests/files/alloc_6a.gno +++ b/gnovm/tests/files/alloc_6a.gno @@ -15,7 +15,7 @@ func main() { } // Output: -// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6554} +// memstats in main after GC: Allocator{maxBytes:100000000, bytes:6542} // TypeCheckError: -// main/files/alloc_6a.gno:8:7: declared and not used: a +// main/alloc_6a.gno:8:7: declared and not used: a diff --git a/gnovm/tests/files/alloc_7.gno b/gnovm/tests/files/alloc_7.gno index a4607f15700..ad746975fb3 100644 --- a/gnovm/tests/files/alloc_7.gno +++ b/gnovm/tests/files/alloc_7.gno @@ -13,7 +13,7 @@ func main() { } // Output: -// MemStats: Allocator{maxBytes:100000000, bytes:5888} +// MemStats: Allocator{maxBytes:100000000, bytes:5876} // TypeCheckError: -// main/files/alloc_7.gno:10:2: declared and not used: s1 +// main/alloc_7.gno:10:2: declared and not used: s1 diff --git a/gnovm/tests/files/array3.gno b/gnovm/tests/files/array3.gno index 8402bbb32b8..78272fcc6ee 100644 --- a/gnovm/tests/files/array3.gno +++ b/gnovm/tests/files/array3.gno @@ -11,4 +11,4 @@ func main() { // runtime error: index out of range [3] with length 3 // TypeCheckError: -// main/files/array3.gno:6:20: index 3 is out of bounds (>= 3) +// main/array3.gno:6:20: index 3 is out of bounds (>= 3) diff --git a/gnovm/tests/files/array4.gno b/gnovm/tests/files/array4.gno index 3e6d2ca2f92..6892022abfb 100644 --- a/gnovm/tests/files/array4.gno +++ b/gnovm/tests/files/array4.gno @@ -8,4 +8,4 @@ func main() { // duplicate index 2 in array or slice literal // TypeCheckError: -// main/files/array4.gno:4:26: duplicate index 2 in array or slice literal; main/files/array4.gno:4:2: declared and not used: a +// main/array4.gno:4:26: duplicate index 2 in array or slice literal; main/array4.gno:4:2: declared and not used: a diff --git a/gnovm/tests/files/array5.gno b/gnovm/tests/files/array5.gno index 922cfd6c705..0ef5bd66451 100644 --- a/gnovm/tests/files/array5.gno +++ b/gnovm/tests/files/array5.gno @@ -8,4 +8,4 @@ func main() { // duplicate index 1 in array or slice literal // TypeCheckError: -// main/files/array5.gno:4:20: duplicate index 1 in array or slice literal; main/files/array5.gno:4:2: declared and not used: a +// main/array5.gno:4:20: duplicate index 1 in array or slice literal; main/array5.gno:4:2: declared and not used: a diff --git a/gnovm/tests/files/assign11.gno b/gnovm/tests/files/assign11.gno index 8f6f22607ad..97e809dde8e 100644 --- a/gnovm/tests/files/assign11.gno +++ b/gnovm/tests/files/assign11.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/assign11.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign11.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values // TypeCheckError: -// main/files/assign11.gno:6:12: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign11.gno:6:12: assignment mismatch: 3 variables but fmt.Println returns 2 values diff --git a/gnovm/tests/files/assign12.gno b/gnovm/tests/files/assign12.gno index b139c6b12ad..ad9e9b4e10e 100644 --- a/gnovm/tests/files/assign12.gno +++ b/gnovm/tests/files/assign12.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/assign12.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign12.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values // TypeCheckError: -// main/files/assign12.gno:6:13: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign12.gno:6:13: assignment mismatch: 3 variables but fmt.Println returns 2 values diff --git a/gnovm/tests/files/assign22.gno b/gnovm/tests/files/assign22.gno index e52d04d66c3..3322ae4a7b7 100644 --- a/gnovm/tests/files/assign22.gno +++ b/gnovm/tests/files/assign22.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/assign22.gno:7:2: assignment operator <<= requires only one expression on lhs and rhs +// main/assign22.gno:7:2: assignment operator <<= requires only one expression on lhs and rhs // TypeCheckError: -// main/files/assign22.gno:7:8: assignment operation <<= requires single-valued expressions; main/files/assign22.gno:4:2: declared and not used: m +// main/assign22.gno:7:8: assignment operation <<= requires single-valued expressions; main/assign22.gno:4:2: declared and not used: m diff --git a/gnovm/tests/files/assign23.gno b/gnovm/tests/files/assign23.gno index 3f35605c428..5f4b8db941f 100644 --- a/gnovm/tests/files/assign23.gno +++ b/gnovm/tests/files/assign23.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/assign23.gno:7:2: assignment operator += requires only one expression on lhs and rhs +// main/assign23.gno:7:2: assignment operator += requires only one expression on lhs and rhs // TypeCheckError: -// main/files/assign23.gno:7:8: assignment operation += requires single-valued expressions; main/files/assign23.gno:4:2: declared and not used: m +// main/assign23.gno:7:8: assignment operation += requires single-valued expressions; main/assign23.gno:4:2: declared and not used: m diff --git a/gnovm/tests/files/assign24.gno b/gnovm/tests/files/assign24.gno index 9b9ce01c0bc..660a0907e49 100644 --- a/gnovm/tests/files/assign24.gno +++ b/gnovm/tests/files/assign24.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/assign24.gno:4:2: assignment mismatch: 2 variable(s) but 1 value(s) +// main/assign24.gno:4:2: assignment mismatch: 2 variable(s) but 1 value(s) // TypeCheckError: -// main/files/assign24.gno:4:10: assignment mismatch: 2 variables but 1 value; main/files/assign24.gno:4:2: declared and not used: a; main/files/assign24.gno:4:5: declared and not used: b +// main/assign24.gno:4:10: assignment mismatch: 2 variables but 1 value; main/assign24.gno:4:2: declared and not used: a; main/assign24.gno:4:5: declared and not used: b diff --git a/gnovm/tests/files/assign25.gno b/gnovm/tests/files/assign25.gno index 73e79575f1f..f83b897e7bd 100644 --- a/gnovm/tests/files/assign25.gno +++ b/gnovm/tests/files/assign25.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/assign25.gno:8:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/assign25.gno:8:2: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: -// main/files/assign25.gno:8:13: assignment mismatch: 3 variables but 2 values +// main/assign25.gno:8:13: assignment mismatch: 3 variables but 2 values diff --git a/gnovm/tests/files/assign25b.gno b/gnovm/tests/files/assign25b.gno index 7e1fbd77fea..bb07ab8dcd6 100644 --- a/gnovm/tests/files/assign25b.gno +++ b/gnovm/tests/files/assign25b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/assign25b.gno:8:2: assignment mismatch: 3 variable(s) but 4 value(s) +// main/assign25b.gno:8:2: assignment mismatch: 3 variable(s) but 4 value(s) // TypeCheckError: -// main/files/assign25b.gno:8:13: assignment mismatch: 3 variables but 4 values +// main/assign25b.gno:8:13: assignment mismatch: 3 variables but 4 values diff --git a/gnovm/tests/files/assign25c.gno b/gnovm/tests/files/assign25c.gno index 8143c93580a..cee43530eb8 100644 --- a/gnovm/tests/files/assign25c.gno +++ b/gnovm/tests/files/assign25c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/assign25c.gno:10:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/assign25c.gno:10:2: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: -// main/files/assign25c.gno:10:13: assignment mismatch: 3 variables but 2 values +// main/assign25c.gno:10:13: assignment mismatch: 3 variables but 2 values diff --git a/gnovm/tests/files/assign25d.gno b/gnovm/tests/files/assign25d.gno index 7f74b8ef779..aa9550d803a 100644 --- a/gnovm/tests/files/assign25d.gno +++ b/gnovm/tests/files/assign25d.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/assign25d.gno:10:2: assignment mismatch: 3 variable(s) but 4 value(s) +// main/assign25d.gno:10:2: assignment mismatch: 3 variable(s) but 4 value(s) // TypeCheckError: -// main/files/assign25d.gno:10:13: assignment mismatch: 3 variables but 4 values +// main/assign25d.gno:10:13: assignment mismatch: 3 variables but 4 values diff --git a/gnovm/tests/files/assign26.gno b/gnovm/tests/files/assign26.gno index 5feda78e47b..4b97268984a 100644 --- a/gnovm/tests/files/assign26.gno +++ b/gnovm/tests/files/assign26.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/assign26.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) +// main/assign26.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: -// main/files/assign26.gno:5:13: assignment mismatch: 3 variables but 1 value; main/files/assign26.gno:5:2: declared and not used: a; main/files/assign26.gno:5:5: declared and not used: b; main/files/assign26.gno:5:8: declared and not used: c +// main/assign26.gno:5:13: assignment mismatch: 3 variables but 1 value; main/assign26.gno:5:2: declared and not used: a; main/assign26.gno:5:5: declared and not used: b; main/assign26.gno:5:8: declared and not used: c diff --git a/gnovm/tests/files/assign27.gno b/gnovm/tests/files/assign27.gno index 8130c6b1902..3cc39a12354 100644 --- a/gnovm/tests/files/assign27.gno +++ b/gnovm/tests/files/assign27.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/assign27.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) +// main/assign27.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: -// main/files/assign27.gno:5:13: assignment mismatch: 3 variables but 1 value; main/files/assign27.gno:5:2: declared and not used: a; main/files/assign27.gno:5:5: declared and not used: b; main/files/assign27.gno:5:8: declared and not used: c +// main/assign27.gno:5:13: assignment mismatch: 3 variables but 1 value; main/assign27.gno:5:2: declared and not used: a; main/assign27.gno:5:5: declared and not used: b; main/assign27.gno:5:8: declared and not used: c diff --git a/gnovm/tests/files/assign28.gno b/gnovm/tests/files/assign28.gno index 544e2a14756..784a19a8934 100644 --- a/gnovm/tests/files/assign28.gno +++ b/gnovm/tests/files/assign28.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/assign28.gno:6:2: assignment mismatch: 2 variable(s) but 3 value(s) +// main/assign28.gno:6:2: assignment mismatch: 2 variable(s) but 3 value(s) // TypeCheckError: -// main/files/assign28.gno:6:10: assignment mismatch: 2 variables but 3 values +// main/assign28.gno:6:10: assignment mismatch: 2 variables but 3 values diff --git a/gnovm/tests/files/assign29.gno b/gnovm/tests/files/assign29.gno index 476eedefd4c..ce43f0dcb89 100644 --- a/gnovm/tests/files/assign29.gno +++ b/gnovm/tests/files/assign29.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/assign29.gno:4:2: struct{} (type) is not an expression +// main/assign29.gno:4:2: struct{} (type) is not an expression // TypeCheckError: -// main/files/assign29.gno:4:7: struct{} (type) is not an expression; main/files/assign29.gno:4:2: declared and not used: t +// main/assign29.gno:4:7: struct{} (type) is not an expression; main/assign29.gno:4:2: declared and not used: t diff --git a/gnovm/tests/files/assign29_native.gno b/gnovm/tests/files/assign29_native.gno index 04f385d4b00..2aa52335610 100644 --- a/gnovm/tests/files/assign29_native.gno +++ b/gnovm/tests/files/assign29_native.gno @@ -14,4 +14,4 @@ func main() { // cannot directly modify readonly tainted object (w/o method): (const (ref(time) package{})).Now // TypeCheckError: -// main/files/assign29_native.gno:8:2: use of package time not in selector; main/files/assign29_native.gno:8:2: cannot assign to time.Now (neither addressable nor a map index expression) +// main/assign29_native.gno:8:2: use of package time not in selector; main/assign29_native.gno:8:2: cannot assign to time.Now (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/assign30.gno b/gnovm/tests/files/assign30.gno index 12ddb6f5b45..98c13be352a 100644 --- a/gnovm/tests/files/assign30.gno +++ b/gnovm/tests/files/assign30.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/assign30.gno:4:2: *struct{} (type) is not an expression +// main/assign30.gno:4:2: *struct{} (type) is not an expression // TypeCheckError: -// main/files/assign30.gno:4:7: *struct{} (type) is not an expression; main/files/assign30.gno:4:2: declared and not used: t +// main/assign30.gno:4:7: *struct{} (type) is not an expression; main/assign30.gno:4:2: declared and not used: t diff --git a/gnovm/tests/files/assign31.gno b/gnovm/tests/files/assign31.gno index c251957d34a..874cada7440 100644 --- a/gnovm/tests/files/assign31.gno +++ b/gnovm/tests/files/assign31.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/assign31.gno:4:2: use of untyped nil in assignment +// main/assign31.gno:4:2: use of untyped nil in assignment // TypeCheckError: -// main/files/assign31.gno:4:7: use of untyped nil in assignment +// main/assign31.gno:4:7: use of untyped nil in assignment diff --git a/gnovm/tests/files/assign33.gno b/gnovm/tests/files/assign33.gno index fdf5c2b3e42..214a8a9ab07 100644 --- a/gnovm/tests/files/assign33.gno +++ b/gnovm/tests/files/assign33.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/assign33.gno:8:6: cannot use foo() (value of type bool) as int value in assignment +// main/assign33.gno:8:6: cannot use foo() (value of type bool) as int value in assignment // TypeCheckError: -// main/files/assign33.gno:8:17: cannot use foo() (value of type bool) as int value in assignment +// main/assign33.gno:8:17: cannot use foo() (value of type bool) as int value in assignment diff --git a/gnovm/tests/files/assign35.gno b/gnovm/tests/files/assign35.gno index e4c7aa59c04..97f425548ab 100644 --- a/gnovm/tests/files/assign35.gno +++ b/gnovm/tests/files/assign35.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/assign35.gno:8:2: multiple-value foo (value of type [int bool]) in single-value context +// main/assign35.gno:8:2: multiple-value foo (value of type [int bool]) in single-value context // TypeCheckError: -// main/files/assign35.gno:8:13: multiple-value foo() (value of type (int, bool)) in single-value context +// main/assign35.gno:8:13: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/assign37.gno b/gnovm/tests/files/assign37.gno index be26a7e5993..9a06ce31837 100644 --- a/gnovm/tests/files/assign37.gno +++ b/gnovm/tests/files/assign37.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/assign37.gno:6:2: f (no value) used as value +// main/assign37.gno:6:2: f (no value) used as value // TypeCheckError: -// main/files/assign37.gno:6:7: f() (no value) used as value; main/files/assign37.gno:6:2: declared and not used: a +// main/assign37.gno:6:7: f() (no value) used as value; main/assign37.gno:6:2: declared and not used: a diff --git a/gnovm/tests/files/assign37b.gno b/gnovm/tests/files/assign37b.gno index 8ccc1548f80..a6b12b7a0e7 100644 --- a/gnovm/tests/files/assign37b.gno +++ b/gnovm/tests/files/assign37b.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/assign37b.gno:8:2: f (no value) used as value +// main/assign37b.gno:8:2: f (no value) used as value // TypeCheckError: -// main/files/assign37b.gno:8:10: f() (no value) used as value; main/files/assign37b.gno:8:15: f() (no value) used as value; main/files/assign37b.gno:8:2: declared and not used: a; main/files/assign37b.gno:8:5: declared and not used: b; main/files/assign37b.gno:3:8: "fmt" imported and not used +// main/assign37b.gno:8:10: f() (no value) used as value; main/assign37b.gno:8:15: f() (no value) used as value; main/assign37b.gno:8:2: declared and not used: a; main/assign37b.gno:8:5: declared and not used: b; main/assign37b.gno:3:8: "fmt" imported and not used diff --git a/gnovm/tests/files/assign38.gno b/gnovm/tests/files/assign38.gno index 43722b36958..399e4c1dded 100644 --- a/gnovm/tests/files/assign38.gno +++ b/gnovm/tests/files/assign38.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/assign38.gno:5:2: cannot use nil as int value in assignment +// main/assign38.gno:5:2: cannot use nil as int value in assignment // TypeCheckError: -// main/files/assign38.gno:5:6: cannot use nil as int value in assignment +// main/assign38.gno:5:6: cannot use nil as int value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno index bbd9e00919f..8b51f51d0c0 100644 --- a/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno @@ -13,4 +13,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno:11:7: cannot use int as int64 +// main/named_unnamed_type2_filetest.gno:11:7: cannot use int as int64 + +// TypeCheckError: +// main/named_unnamed_type2_filetest.gno:11:23: cannot use nlist (variable of slice type nat) as []int64 value in argument to append 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 e41e6c6f21f..d5a40c0b5b1 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,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/method/declaredType6_filetest.gno:15:2: cannot use []main.c as []main.word +// main/declaredType6_filetest.gno:15:2: cannot use []main.c as []main.word + +// TypeCheckError: +// main/declaredType6_filetest.gno:15:8: cannot use []c{…} (value of type []c) as nat value in assignment 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 673c48725b8..1cb60a74c8a 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,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/method/declaredType6b_filetest.gno:15:2: cannot use []uint as []main.word +// main/declaredType6b_filetest.gno:15:2: cannot use []uint as []main.word + +// TypeCheckError: +// main/declaredType6b_filetest.gno:15:8: cannot use []uint{…} (value of type []uint) as nat value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/more/assgin_interface2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/assgin_interface2_filetest.gno index c30933f45ba..b1ba2d20283 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/assgin_interface2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/assgin_interface2_filetest.gno @@ -12,3 +12,6 @@ func main() { // Output: // (slice[(1 int)] main.nat) + +// TypeCheckError: +// main/assgin_interface2_filetest.gno:6:6: declared and not used: a diff --git a/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno index b2cdc14ff77..471f7a04ad8 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno @@ -15,4 +15,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/more/assgin_two_filetest.gno:11:2: cannot use main.nat2 as main.nat without explicit conversion +// main/assgin_two_filetest.gno:11:2: cannot use main.nat2 as main.nat without explicit conversion + +// TypeCheckError: +// main/assgin_two_filetest.gno:11:6: cannot use b (variable of slice type nat2) as nat value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/more/errors2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/errors2_filetest.gno index 2588b904a77..d41550994e5 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/errors2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/errors2_filetest.gno @@ -15,3 +15,6 @@ func main() { // Output: // some error + +// TypeCheckError: +// main/errors2_filetest.gno:12:2: declared and not used: b diff --git a/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno index 7b6be664d96..8000770d7f0 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno @@ -12,4 +12,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/more/return_interface1_filetest.gno:10:2: cannot use interface {} as uint +// main/return_interface1_filetest.gno:10:2: cannot use interface {} as uint + +// TypeCheckError: +// main/return_interface1_filetest.gno:10:6: cannot use x1() (value of interface type any) as uint value in assignment: need type assertion; main/return_interface1_filetest.gno:9:6: declared and not used: a diff --git a/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno index 4fcc90eaa83..085d0188563 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno @@ -16,4 +16,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/more/return_interface_filetest.gno:13:2: cannot use interface {} as []int +// main/return_interface_filetest.gno:13:2: cannot use interface {} as []int + +// TypeCheckError: +// main/return_interface_filetest.gno:13:6: cannot use x() (value of interface type any) as nat value in assignment: need type assertion diff --git a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno index 0c7b03df575..0e259226166 100644 --- a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno @@ -14,4 +14,7 @@ func main() { } // Error: -// main/files/assign_unnamed_type/unnamedtype0b_filetest.gno:11:2: cannot use []main.word as []int +// main/unnamedtype0b_filetest.gno:11:2: cannot use []main.word as []int + +// TypeCheckError: +// main/unnamedtype0b_filetest.gno:11:6: cannot use b (variable of type []word) as nat value in assignment diff --git a/gnovm/tests/files/blankidentifier0.gno b/gnovm/tests/files/blankidentifier0.gno index 83ccc62c8b2..a82f18df127 100644 --- a/gnovm/tests/files/blankidentifier0.gno +++ b/gnovm/tests/files/blankidentifier0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/blankidentifier0.gno:4:6: cannot use _ as value or type +// main/blankidentifier0.gno:4:6: cannot use _ as value or type // TypeCheckError: -// main/files/blankidentifier0.gno:4:6: cannot use _ as value or type +// main/blankidentifier0.gno:4:6: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier2.gno b/gnovm/tests/files/blankidentifier2.gno index aff69d225c5..97614beae62 100644 --- a/gnovm/tests/files/blankidentifier2.gno +++ b/gnovm/tests/files/blankidentifier2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/blankidentifier2.gno:4:6: cannot use _ as value or type +// main/blankidentifier2.gno:4:6: cannot use _ as value or type // TypeCheckError: -// main/files/blankidentifier2.gno:4:8: cannot use _ as value or type +// main/blankidentifier2.gno:4:8: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier3.gno b/gnovm/tests/files/blankidentifier3.gno index 794c5034350..d7ef4378ee2 100644 --- a/gnovm/tests/files/blankidentifier3.gno +++ b/gnovm/tests/files/blankidentifier3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/blankidentifier3.gno:3:6: cannot use _ as value or type +// main/blankidentifier3.gno:3:6: cannot use _ as value or type // TypeCheckError: -// main/files/blankidentifier3.gno:3:8: cannot use _ as value or type +// main/blankidentifier3.gno:3:8: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier6.gno b/gnovm/tests/files/blankidentifier6.gno index 531a520491d..90954b4c4e7 100644 --- a/gnovm/tests/files/blankidentifier6.gno +++ b/gnovm/tests/files/blankidentifier6.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/files/blankidentifier6.gno:18:13: cannot use _ as value or type +// main/blankidentifier6.gno:18:13: cannot use _ as value or type // TypeCheckError: -// main/files/blankidentifier6.gno:18:13: cannot use _ as value or type +// main/blankidentifier6.gno:18:13: cannot use _ as value or type diff --git a/gnovm/tests/files/block2.gno b/gnovm/tests/files/block2.gno index 6738c76bf40..065524e1fcd 100644 --- a/gnovm/tests/files/block2.gno +++ b/gnovm/tests/files/block2.gno @@ -547,4 +547,4 @@ func main() { } // Error: -// main/files/block2.gno:419:129: exceeded maximum VPBlock depth (127) +// main/block2.gno:419:129: exceeded maximum VPBlock depth (127) diff --git a/gnovm/tests/files/bltn0.gno b/gnovm/tests/files/bltn0.gno index 89fc32b5a41..5a34457690d 100644 --- a/gnovm/tests/files/bltn0.gno +++ b/gnovm/tests/files/bltn0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/bltn0.gno:4:7: use of builtin println not in function call +// main/bltn0.gno:4:7: use of builtin println not in function call // TypeCheckError: -// main/files/bltn0.gno:4:7: println (built-in) must be called +// main/bltn0.gno:4:7: println (built-in) must be called diff --git a/gnovm/tests/files/bool6.gno b/gnovm/tests/files/bool6.gno index e7ba8390932..eb367481eee 100644 --- a/gnovm/tests/files/bool6.gno +++ b/gnovm/tests/files/bool6.gno @@ -9,7 +9,7 @@ func X() string { } // Error: -// main/files/bool6.gno:8:9: operator || not defined on: StringKind +// main/bool6.gno:8:9: operator || not defined on: StringKind // TypeCheckError: -// main/files/bool6.gno:8:9: invalid operation: operator || not defined on "hello" (untyped string constant) +// main/bool6.gno:8:9: invalid operation: operator || not defined on "hello" (untyped string constant) diff --git a/gnovm/tests/files/break0.gno b/gnovm/tests/files/break0.gno index a7c71282a9b..3e6207286b4 100644 --- a/gnovm/tests/files/break0.gno +++ b/gnovm/tests/files/break0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/break0.gno:4:2: break statement out of place +// main/break0.gno:4:2: break statement out of place // TypeCheckError: -// main/files/break0.gno:4:2: break not in for, switch, or select statement +// main/break0.gno:4:2: break not in for, switch, or select statement diff --git a/gnovm/tests/files/cap10.gno b/gnovm/tests/files/cap10.gno index 94cca338f97..3dcf1eab218 100644 --- a/gnovm/tests/files/cap10.gno +++ b/gnovm/tests/files/cap10.gno @@ -8,4 +8,4 @@ func main() { // unexpected type for cap(): struct{A int} // TypeCheckError: -// main/files/cap10.gno:4:21: invalid argument: struct{A int}{} (value of type struct{A int}) for built-in cap +// main/cap10.gno:4:21: invalid argument: struct{A int}{} (value of type struct{A int}) for built-in cap diff --git a/gnovm/tests/files/cap7.gno b/gnovm/tests/files/cap7.gno index 9f059ec4a16..92650747ce5 100644 --- a/gnovm/tests/files/cap7.gno +++ b/gnovm/tests/files/cap7.gno @@ -9,4 +9,4 @@ func main() { // unexpected type for cap(): string // TypeCheckError: -// main/files/cap7.gno:5:21: invalid argument: s (variable of type string) for built-in cap +// main/cap7.gno:5:21: invalid argument: s (variable of type string) for built-in cap diff --git a/gnovm/tests/files/cap8.gno b/gnovm/tests/files/cap8.gno index 99bcf6e4aa9..4c8e504394a 100644 --- a/gnovm/tests/files/cap8.gno +++ b/gnovm/tests/files/cap8.gno @@ -9,4 +9,4 @@ func main() { // unexpected type for cap(): *int // TypeCheckError: -// main/files/cap8.gno:5:21: invalid argument: i (variable of type *int) for built-in cap +// main/cap8.gno:5:21: invalid argument: i (variable of type *int) for built-in cap diff --git a/gnovm/tests/files/cap9.gno b/gnovm/tests/files/cap9.gno index a7025a5d064..a1b66734d64 100644 --- a/gnovm/tests/files/cap9.gno +++ b/gnovm/tests/files/cap9.gno @@ -9,4 +9,4 @@ func main() { // unexpected type for cap(): *int // TypeCheckError: -// main/files/cap9.gno:5:21: invalid argument: i (variable of type *int) for built-in cap +// main/cap9.gno:5:21: invalid argument: i (variable of type *int) for built-in cap diff --git a/gnovm/tests/files/circular_constant.gno b/gnovm/tests/files/circular_constant.gno index b87a64c3b69..3ca2f5b7acc 100644 --- a/gnovm/tests/files/circular_constant.gno +++ b/gnovm/tests/files/circular_constant.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/circular_constant.gno:3:7: constant definition loop with A +// main/circular_constant.gno:3:7: constant definition loop with A // TypeCheckError: -// main/files/circular_constant.gno:3:7: initialization cycle for A; main/files/circular_constant.gno:3:7: A refers to B; main/files/circular_constant.gno:4:7: B refers to A +// main/circular_constant.gno:3:7: initialization cycle for A; main/circular_constant.gno:3:7: A refers to B; main/circular_constant.gno:4:7: B refers to A diff --git a/gnovm/tests/files/closure.gno b/gnovm/tests/files/closure.gno index 932e4d69ff1..2085bc78ac6 100644 --- a/gnovm/tests/files/closure.gno +++ b/gnovm/tests/files/closure.gno @@ -13,7 +13,7 @@ var b = func() { } // Error: -// main/files/closure.gno:7:5: constant definition loop with a +// main/closure.gno:7:5: constant definition loop with a // TypeCheckError: -// main/files/closure.gno:7:5: initialization cycle for a; main/files/closure.gno:7:5: a refers to b; main/files/closure.gno:11:5: b refers to a +// main/closure.gno:7:5: initialization cycle for a; main/closure.gno:7:5: a refers to b; main/closure.gno:11:5: b refers to a diff --git a/gnovm/tests/files/closure9.gno b/gnovm/tests/files/closure9.gno index 41b5a16b2b0..98392401f48 100644 --- a/gnovm/tests/files/closure9.gno +++ b/gnovm/tests/files/closure9.gno @@ -26,4 +26,4 @@ func makeClosure(a int) (b int, c func(bool)) { // 1 2 0 // TypeCheckError: -// main/files/closure9.gno:8:2: declared and not used: b +// main/closure9.gno:8:2: declared and not used: b diff --git a/gnovm/tests/files/comp5.gno b/gnovm/tests/files/comp5.gno index dd190deff8a..718520199d1 100644 --- a/gnovm/tests/files/comp5.gno +++ b/gnovm/tests/files/comp5.gno @@ -23,4 +23,4 @@ func main() { // znil == y true // TypeCheckError: -// main/files/comp5.gno:7:2: declared and not used: x +// main/comp5.gno:7:2: declared and not used: x diff --git a/gnovm/tests/files/composite15.gno b/gnovm/tests/files/composite15.gno index 3851da0ffbe..de8cac0d09d 100644 --- a/gnovm/tests/files/composite15.gno +++ b/gnovm/tests/files/composite15.gno @@ -13,4 +13,4 @@ func main() { // slice[(0 int),(2 int),(0 int),(4 int)] // TypeCheckError: -// main/files/composite15.gno:6:3: index a must be integer constant; main/files/composite15.gno:7:3: index c must be integer constant +// main/composite15.gno:6:3: index a must be integer constant; main/composite15.gno:7:3: index c must be integer constant diff --git a/gnovm/tests/files/composite16.gno b/gnovm/tests/files/composite16.gno index 3262b6350cb..fd6ee6dc4dc 100644 --- a/gnovm/tests/files/composite16.gno +++ b/gnovm/tests/files/composite16.gno @@ -21,4 +21,4 @@ func main() { // slice[(0 int),(2 int),(0 int),(4 int)] // TypeCheckError: -// main/files/composite16.gno:10:3: index x(1) must be integer constant; main/files/composite16.gno:11:3: index x(3) must be integer constant +// main/composite16.gno:10:3: index x(1) must be integer constant; main/composite16.gno:11:3: index x(3) must be integer constant diff --git a/gnovm/tests/files/const23.gno b/gnovm/tests/files/const23.gno index b27d02a1a86..0d641f2c0db 100644 --- a/gnovm/tests/files/const23.gno +++ b/gnovm/tests/files/const23.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/const23.gno:6:8: invalid constant type []string +// main/const23.gno:6:8: invalid constant type []string // TypeCheckError: -// main/files/const23.gno:6:10: invalid constant type []string +// main/const23.gno:6:10: invalid constant type []string diff --git a/gnovm/tests/files/const25.gno b/gnovm/tests/files/const25.gno index e0091bd0c90..629a7d829c2 100644 --- a/gnovm/tests/files/const25.gno +++ b/gnovm/tests/files/const25.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant +// main/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant // TypeCheckError: -// main/files/const25.gno:6:12: []string{…} (value of type []string) is not constant +// main/const25.gno:6:12: []string{…} (value of type []string) is not constant diff --git a/gnovm/tests/files/const26.gno b/gnovm/tests/files/const26.gno index 80b1704d8ae..c454d89b912 100644 --- a/gnovm/tests/files/const26.gno +++ b/gnovm/tests/files/const26.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/const26.gno:10:8: v() (value of type string) is not constant +// main/const26.gno:10:8: v() (value of type string) is not constant // TypeCheckError: -// main/files/const26.gno:10:12: v() (value of type string) is not constant +// main/const26.gno:10:12: v() (value of type string) is not constant diff --git a/gnovm/tests/files/const27.gno b/gnovm/tests/files/const27.gno index 9ee15e948a6..cb3ef82e39b 100644 --- a/gnovm/tests/files/const27.gno +++ b/gnovm/tests/files/const27.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/const27.gno:11:8: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant +// main/const27.gno:11:8: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant // TypeCheckError: -// main/files/const27.gno:11:11: missing init expr for ok; main/files/const27.gno:11:16: i.(int) (comma, ok expression of type int) is not constant +// main/const27.gno:11:11: missing init expr for ok; main/const27.gno:11:16: i.(int) (comma, ok expression of type int) is not constant diff --git a/gnovm/tests/files/const28.gno b/gnovm/tests/files/const28.gno index 4bff2ea8108..bc32782aa75 100644 --- a/gnovm/tests/files/const28.gno +++ b/gnovm/tests/files/const28.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const28.gno:7:8: s[(const (0 int))] (variable of type string) is not constant +// main/const28.gno:7:8: s[(const (0 int))] (variable of type string) is not constant // TypeCheckError: -// main/files/const28.gno:7:11: missing init expr for ok; main/files/const28.gno:7:16: s[0] (variable of type string) is not constant +// main/const28.gno:7:11: missing init expr for ok; main/const28.gno:7:16: s[0] (variable of type string) is not constant diff --git a/gnovm/tests/files/const29.gno b/gnovm/tests/files/const29.gno index d6f9a4a7532..b35cd6708f4 100644 --- a/gnovm/tests/files/const29.gno +++ b/gnovm/tests/files/const29.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const29.gno:7:8: s (variable of type string) is not constant +// main/const29.gno:7:8: s (variable of type string) is not constant // TypeCheckError: -// main/files/const29.gno:7:12: s (variable of type string) is not constant +// main/const29.gno:7:12: s (variable of type string) is not constant diff --git a/gnovm/tests/files/const30.gno b/gnovm/tests/files/const30.gno index 77915f5db4a..cbc15c1804e 100644 --- a/gnovm/tests/files/const30.gno +++ b/gnovm/tests/files/const30.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/const30.gno:10:8: v (no value) used as value +// main/const30.gno:10:8: v (no value) used as value // TypeCheckError: -// main/files/const30.gno:10:12: v() (no value) used as value +// main/const30.gno:10:12: v() (no value) used as value diff --git a/gnovm/tests/files/const31.gno b/gnovm/tests/files/const31.gno index afda0cb8bb2..8e40aaa52e5 100644 --- a/gnovm/tests/files/const31.gno +++ b/gnovm/tests/files/const31.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/const31.gno:10:8: (const (v func() (string, string)))() (variable of type (string,string)) is not constant +// main/const31.gno:10:8: (const (v func() (string, string)))() (variable of type (string,string)) is not constant // TypeCheckError: -// main/files/const31.gno:10:11: missing init expr for v; main/files/const31.gno:10:15: multiple-value v() (value of type (string, string)) in single-value context +// main/const31.gno:10:11: missing init expr for v; main/const31.gno:10:15: multiple-value v() (value of type (string, string)) in single-value context diff --git a/gnovm/tests/files/const32.gno b/gnovm/tests/files/const32.gno index e199a1a1b8f..8d0cf2aae00 100644 --- a/gnovm/tests/files/const32.gno +++ b/gnovm/tests/files/const32.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant +// main/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant // TypeCheckError: -// main/files/const32.gno:6:12: 1 + 2 + len([]string{}) (value of type int) is not constant +// main/const32.gno:6:12: 1 + 2 + len([]string{}) (value of type int) is not constant diff --git a/gnovm/tests/files/const33.gno b/gnovm/tests/files/const33.gno index 8b7100cbd1c..0492bcb2204 100644 --- a/gnovm/tests/files/const33.gno +++ b/gnovm/tests/files/const33.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/const33.gno:6:7: x (variable of type int) is not constant +// main/const33.gno:6:7: x (variable of type int) is not constant // TypeCheckError: -// main/files/const33.gno:6:11: x == y (untyped bool value) is not constant +// main/const33.gno:6:11: x == y (untyped bool value) is not constant diff --git a/gnovm/tests/files/const34.gno b/gnovm/tests/files/const34.gno index df77a34ff87..ff7a7c60725 100644 --- a/gnovm/tests/files/const34.gno +++ b/gnovm/tests/files/const34.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/const34.gno:3:7: func func(){ (const (println func(...interface {})))((const ("hey" string))) } (variable of type func()) is not constant +// main/const34.gno:3:7: func func(){ (const (println func(...interface {})))((const ("hey" string))) } (variable of type func()) is not constant // TypeCheckError: -// main/files/const34.gno:3:11: (func() literal) (value of type func()) is not constant +// main/const34.gno:3:11: (func() literal) (value of type func()) is not constant diff --git a/gnovm/tests/files/const35.gno b/gnovm/tests/files/const35.gno index 641e3b0f918..7b063636f4c 100644 --- a/gnovm/tests/files/const35.gno +++ b/gnovm/tests/files/const35.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const35.gno:5:7: x (variable of type int) is not constant +// main/const35.gno:5:7: x (variable of type int) is not constant // TypeCheckError: -// main/files/const35.gno:5:12: +(1 << x) (untyped int value) is not constant +// main/const35.gno:5:12: +(1 << x) (untyped int value) is not constant diff --git a/gnovm/tests/files/const36.gno b/gnovm/tests/files/const36.gno index 8d9f198c5ae..5c7857ffc9f 100644 --- a/gnovm/tests/files/const36.gno +++ b/gnovm/tests/files/const36.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/const36.gno:9:8: s.x (variable of type int) is not constant +// main/const36.gno:9:8: s.x (variable of type int) is not constant // TypeCheckError: -// main/files/const36.gno:9:12: s.x (variable of type int) is not constant +// main/const36.gno:9:12: s.x (variable of type int) is not constant diff --git a/gnovm/tests/files/const37_native.gno b/gnovm/tests/files/const37_native.gno index 151d4f7731b..ad35bb5cd28 100644 --- a/gnovm/tests/files/const37_native.gno +++ b/gnovm/tests/files/const37_native.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/const37_native.gno:6:8: time.UTC (variable of type *time.Location) is not constant +// main/const37_native.gno:6:8: time.UTC (variable of type *time.Location) is not constant // TypeCheckError: -// main/files/const37_native.gno:6:12: time.UTC (variable of type *time.Location) is not constant +// main/const37_native.gno:6:12: time.UTC (variable of type *time.Location) is not constant diff --git a/gnovm/tests/files/const37_stdlibs.gno b/gnovm/tests/files/const37_stdlibs.gno index 6a202270d82..45452f44e3e 100644 --- a/gnovm/tests/files/const37_stdlibs.gno +++ b/gnovm/tests/files/const37_stdlibs.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/const37_stdlibs.gno:6:8: time.UTC (variable of type *time.Location) is not constant +// main/const37_stdlibs.gno:6:8: time.UTC (variable of type *time.Location) is not constant // TypeCheckError: -// main/files/const37_stdlibs.gno:6:12: time.UTC (variable of type *time.Location) is not constant +// main/const37_stdlibs.gno:6:12: time.UTC (variable of type *time.Location) is not constant diff --git a/gnovm/tests/files/const38.gno b/gnovm/tests/files/const38.gno index c51bdf3b525..bcb96a42f26 100644 --- a/gnovm/tests/files/const38.gno +++ b/gnovm/tests/files/const38.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/const38.gno:7:8: v.Denom (variable of type string) is not constant +// main/const38.gno:7:8: v.Denom (variable of type string) is not constant // TypeCheckError: -// main/files/const38.gno:7:12: v.Denom (variable of type string) is not constant +// main/const38.gno:7:12: v.Denom (variable of type string) is not constant diff --git a/gnovm/tests/files/const39.gno b/gnovm/tests/files/const39.gno index b843c5b36c6..737e14e7c50 100644 --- a/gnovm/tests/files/const39.gno +++ b/gnovm/tests/files/const39.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/const39.gno:10:8: typeval{main.T}.Mv (variable of type func(main.T, int) int) is not constant +// main/const39.gno:10:8: typeval{main.T}.Mv (variable of type func(main.T, int) int) is not constant // TypeCheckError: -// main/files/const39.gno:10:12: T.Mv (value of type func(tv T, a int) int) is not constant +// main/const39.gno:10:12: T.Mv (value of type func(tv T, a int) int) is not constant diff --git a/gnovm/tests/files/const40.gno b/gnovm/tests/files/const40.gno index 4ee80ceff65..2edf7e8879f 100644 --- a/gnovm/tests/files/const40.gno +++ b/gnovm/tests/files/const40.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/const40.gno:4:8: [(const (0 int))](const-type string){} (variable of type [0]string) is not constant +// main/const40.gno:4:8: [(const (0 int))](const-type string){} (variable of type [0]string) is not constant // TypeCheckError: -// main/files/const40.gno:4:12: [0]string{} (value of type [0]string) is not constant +// main/const40.gno:4:12: [0]string{} (value of type [0]string) is not constant diff --git a/gnovm/tests/files/const41.gno b/gnovm/tests/files/const41.gno index ed009dddd35..36876159da3 100644 --- a/gnovm/tests/files/const41.gno +++ b/gnovm/tests/files/const41.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/const41.gno:4:8: invalid constant type [0]string +// main/const41.gno:4:8: invalid constant type [0]string // TypeCheckError: -// main/files/const41.gno:4:10: invalid constant type [0]string +// main/const41.gno:4:10: invalid constant type [0]string diff --git a/gnovm/tests/files/const42.gno b/gnovm/tests/files/const42.gno index 58a3987f8c8..45e7a251623 100644 --- a/gnovm/tests/files/const42.gno +++ b/gnovm/tests/files/const42.gno @@ -5,4 +5,4 @@ func main() { } // TypeCheckError: -// main/files/const42.gno:4:8: missing init expr for t +// main/const42.gno:4:8: missing init expr for t diff --git a/gnovm/tests/files/const43.gno b/gnovm/tests/files/const43.gno index a47483b2c5b..99e3bf223c9 100644 --- a/gnovm/tests/files/const43.gno +++ b/gnovm/tests/files/const43.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/const43.gno:6:8: a (variable of type [2]int) is not constant +// main/const43.gno:6:8: a (variable of type [2]int) is not constant // TypeCheckError: -// main/files/const43.gno:6:12: a (variable of type [2]int) is not constant +// main/const43.gno:6:12: a (variable of type [2]int) is not constant diff --git a/gnovm/tests/files/const44.gno b/gnovm/tests/files/const44.gno index 16196e2d14d..3c85abd8280 100644 --- a/gnovm/tests/files/const44.gno +++ b/gnovm/tests/files/const44.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/const44.gno:3:7: (const (undefined)) (variable of type interface {}) is not constant +// main/const44.gno:3:7: (const (undefined)) (variable of type interface {}) is not constant // TypeCheckError: -// main/files/const44.gno:3:11: any(nil) (value of interface type any) is not constant +// main/const44.gno:3:11: any(nil) (value of interface type any) is not constant diff --git a/gnovm/tests/files/const45_b.gno b/gnovm/tests/files/const45_b.gno index df01afcfda4..df5f48bc664 100644 --- a/gnovm/tests/files/const45_b.gno +++ b/gnovm/tests/files/const45_b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/const45_b.gno:7:7: typeval{main.MyStruct}{arr: [](const-type int){(const (1 int)), (const (2 int))}}.arr (variable of type []int) is not constant +// main/const45_b.gno:7:7: typeval{main.MyStruct}{arr: [](const-type int){(const (1 int)), (const (2 int))}}.arr (variable of type []int) is not constant // TypeCheckError: -// main/files/const45_b.gno:7:11: len(MyStruct{…}.arr) (value of type int) is not constant +// main/const45_b.gno:7:11: len(MyStruct{…}.arr) (value of type int) is not constant diff --git a/gnovm/tests/files/const48.gno b/gnovm/tests/files/const48.gno index 79423e18f95..5f8610bd5f3 100644 --- a/gnovm/tests/files/const48.gno +++ b/gnovm/tests/files/const48.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/const48.gno:4:8: map[(const-type string)] [](const-type int){(const ("arr" string)): (const-type []int){(const (1 int)), (const (2 int))}} (variable of type map[string][]int) is not constant +// main/const48.gno:4:8: map[(const-type string)] [](const-type int){(const ("arr" string)): (const-type []int){(const (1 int)), (const (2 int))}} (variable of type map[string][]int) is not constant // TypeCheckError: -// main/files/const48.gno:4:12: len(map[string][]int{…}) (value of type int) is not constant +// main/const48.gno:4:12: len(map[string][]int{…}) (value of type int) is not constant diff --git a/gnovm/tests/files/const49.gno b/gnovm/tests/files/const49.gno index 8974fe65d75..9e74787d87d 100644 --- a/gnovm/tests/files/const49.gno +++ b/gnovm/tests/files/const49.gno @@ -16,4 +16,4 @@ func main() { // 2 // TypeCheckError: -// main/files/const49.gno:3:8: "io" imported and not used +// main/const49.gno:3:8: "io" imported and not used diff --git a/gnovm/tests/files/const50.gno b/gnovm/tests/files/const50.gno index c95b907af09..dd51c516ed9 100644 --- a/gnovm/tests/files/const50.gno +++ b/gnovm/tests/files/const50.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const50.gno:5:7: x (variable of type string) is not constant +// main/const50.gno:5:7: x (variable of type string) is not constant // TypeCheckError: -// main/files/const50.gno:5:11: len(x) (value of type int) is not constant +// main/const50.gno:5:11: len(x) (value of type int) is not constant diff --git a/gnovm/tests/files/const55.gno b/gnovm/tests/files/const55.gno index 3c9a0c1e6e5..7805139b662 100644 --- a/gnovm/tests/files/const55.gno +++ b/gnovm/tests/files/const55.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/const55.gno:5:2: assignment mismatch: 1 variable(s) but 2 value(s) +// main/const55.gno:5:2: assignment mismatch: 1 variable(s) but 2 value(s) // TypeCheckError: -// main/files/const55.gno:5:2: extra init expr at main/files/const55.gno:4:2 +// main/const55.gno:5:2: extra init expr at main/const55.gno:4:2 diff --git a/gnovm/tests/files/const55a.gno b/gnovm/tests/files/const55a.gno index 5a9b4028de6..05147685bac 100644 --- a/gnovm/tests/files/const55a.gno +++ b/gnovm/tests/files/const55a.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/const55a.gno:5:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/const55a.gno:5:2: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: -// main/files/const55a.gno:5:8: missing init expr for l +// main/const55a.gno:5:8: missing init expr for l diff --git a/gnovm/tests/files/const60.gno b/gnovm/tests/files/const60.gno index eb1fa4c74b1..5d8abef4217 100644 --- a/gnovm/tests/files/const60.gno +++ b/gnovm/tests/files/const60.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const60.gno:4:6: bigint underflows target kind +// main/const60.gno:4:6: bigint underflows target kind // TypeCheckError: -// main/files/const60.gno:4:11: constant -2 overflows uint +// main/const60.gno:4:11: constant -2 overflows uint diff --git a/gnovm/tests/files/const61.gno b/gnovm/tests/files/const61.gno index ce3fd699913..e478bcfd7f2 100644 --- a/gnovm/tests/files/const61.gno +++ b/gnovm/tests/files/const61.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/const61.gno:4:6: bigint underflows target kind +// main/const61.gno:4:6: bigint underflows target kind // TypeCheckError: -// main/files/const61.gno:4:12: constant -1 overflows uint8 +// main/const61.gno:4:12: constant -1 overflows uint8 diff --git a/gnovm/tests/files/const9.gno b/gnovm/tests/files/const9.gno index 5267869040d..67e3fd5cd12 100644 --- a/gnovm/tests/files/const9.gno +++ b/gnovm/tests/files/const9.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/const9.gno:5:2: constant definition loop with b +// main/const9.gno:5:2: constant definition loop with b // TypeCheckError: -// main/files/const9.gno:6:2: initialization cycle for c; main/files/const9.gno:6:2: c refers to d; main/files/const9.gno:7:2: d refers to e; main/files/const9.gno:8:2: e refers to b; main/files/const9.gno:5:2: b refers to c; main/files/const9.gno:5:2: initialization cycle for b; main/files/const9.gno:5:2: b refers to c; main/files/const9.gno:6:2: c refers to d; main/files/const9.gno:7:2: d refers to e; main/files/const9.gno:8:2: e refers to b +// main/const9.gno:6:2: initialization cycle for c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b; main/const9.gno:5:2: b refers to c; main/const9.gno:5:2: initialization cycle for b; main/const9.gno:5:2: b refers to c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b diff --git a/gnovm/tests/files/cont3.gno b/gnovm/tests/files/cont3.gno index def25335acd..e064c78030d 100644 --- a/gnovm/tests/files/cont3.gno +++ b/gnovm/tests/files/cont3.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/cont3.gno:4:2: continue statement out of place +// main/cont3.gno:4:2: continue statement out of place // TypeCheckError: -// main/files/cont3.gno:4:2: continue not in for statement +// main/cont3.gno:4:2: continue not in for statement diff --git a/gnovm/tests/files/convert4.gno b/gnovm/tests/files/convert4.gno index 5467ecc2d6a..3c4e6800d69 100644 --- a/gnovm/tests/files/convert4.gno +++ b/gnovm/tests/files/convert4.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/convert4.gno:4:10: cannot convert (const (undefined)) to IntKind +// main/convert4.gno:4:10: cannot convert (const (undefined)) to IntKind // TypeCheckError: -// main/files/convert4.gno:4:14: cannot convert nil to type int +// main/convert4.gno:4:14: cannot convert nil to type int diff --git a/gnovm/tests/files/convert5.gno b/gnovm/tests/files/convert5.gno index 58f78fc89c7..77a1398b17b 100644 --- a/gnovm/tests/files/convert5.gno +++ b/gnovm/tests/files/convert5.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/convert5.gno:3:1: cannot convert (const (undefined)) to IntKind +// main/convert5.gno:3:1: cannot convert (const (undefined)) to IntKind // TypeCheckError: -// main/files/convert5.gno:5:22: cannot use nil as int value in argument to append; main/files/convert5.gno:5:27: cannot use nil as int value in argument to append +// main/convert5.gno:5:22: cannot use nil as int value in argument to append; main/convert5.gno:5:27: cannot use nil as int value in argument to append diff --git a/gnovm/tests/files/convert6.gno b/gnovm/tests/files/convert6.gno index db6885c3563..cc926ae01ee 100644 --- a/gnovm/tests/files/convert6.gno +++ b/gnovm/tests/files/convert6.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6.gno:5:10: cannot convert constant of type IntKind to UintKind +// main/convert6.gno:5:10: cannot convert constant of type IntKind to UintKind // TypeCheckError: -// main/files/convert6.gno:5:15: constant -1 overflows uint +// main/convert6.gno:5:15: constant -1 overflows uint diff --git a/gnovm/tests/files/convert6a.gno b/gnovm/tests/files/convert6a.gno index 6edafaa0434..5fa4d162170 100644 --- a/gnovm/tests/files/convert6a.gno +++ b/gnovm/tests/files/convert6a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6a.gno:5:10: cannot convert constant of type IntKind to Uint8Kind +// main/convert6a.gno:5:10: cannot convert constant of type IntKind to Uint8Kind // TypeCheckError: -// main/files/convert6a.gno:5:16: constant -1 overflows uint8 +// main/convert6a.gno:5:16: constant -1 overflows uint8 diff --git a/gnovm/tests/files/convert6b.gno b/gnovm/tests/files/convert6b.gno index 6ecb12e7424..f59e4fd8032 100644 --- a/gnovm/tests/files/convert6b.gno +++ b/gnovm/tests/files/convert6b.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6b.gno:5:10: cannot convert constant of type IntKind to Uint16Kind +// main/convert6b.gno:5:10: cannot convert constant of type IntKind to Uint16Kind // TypeCheckError: -// main/files/convert6b.gno:5:17: constant -1 overflows uint16 +// main/convert6b.gno:5:17: constant -1 overflows uint16 diff --git a/gnovm/tests/files/convert6c.gno b/gnovm/tests/files/convert6c.gno index e5b86791ff9..2b66f53fefa 100644 --- a/gnovm/tests/files/convert6c.gno +++ b/gnovm/tests/files/convert6c.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6c.gno:5:10: cannot convert constant of type IntKind to Uint32Kind +// main/convert6c.gno:5:10: cannot convert constant of type IntKind to Uint32Kind // TypeCheckError: -// main/files/convert6c.gno:5:17: constant -1 overflows uint32 +// main/convert6c.gno:5:17: constant -1 overflows uint32 diff --git a/gnovm/tests/files/convert6d.gno b/gnovm/tests/files/convert6d.gno index b04300af032..4637193198f 100644 --- a/gnovm/tests/files/convert6d.gno +++ b/gnovm/tests/files/convert6d.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6d.gno:5:10: cannot convert constant of type IntKind to Uint64Kind +// main/convert6d.gno:5:10: cannot convert constant of type IntKind to Uint64Kind // TypeCheckError: -// main/files/convert6d.gno:5:17: constant -1 overflows uint64 +// main/convert6d.gno:5:17: constant -1 overflows uint64 diff --git a/gnovm/tests/files/convert6e.gno b/gnovm/tests/files/convert6e.gno index ddd37147717..ef448c95742 100644 --- a/gnovm/tests/files/convert6e.gno +++ b/gnovm/tests/files/convert6e.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert6e.gno:5:10: cannot convert constant of type Float32Kind to Int32Kind +// main/convert6e.gno:5:10: cannot convert constant of type Float32Kind to Int32Kind // TypeCheckError: -// main/files/convert6e.gno:5:16: cannot convert a (constant 1.5 of type float32) to type int32 +// main/convert6e.gno:5:16: cannot convert a (constant 1.5 of type float32) to type int32 diff --git a/gnovm/tests/files/convert7.gno b/gnovm/tests/files/convert7.gno index 89b110729e2..1fe04e43343 100644 --- a/gnovm/tests/files/convert7.gno +++ b/gnovm/tests/files/convert7.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/convert7.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type +// main/convert7.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type // TypeCheckError: -// main/files/convert7.gno:4:16: cannot convert 1.5 (untyped float constant) to type int32 +// main/convert7.gno:4:16: cannot convert 1.5 (untyped float constant) to type int32 diff --git a/gnovm/tests/files/convert7a.gno b/gnovm/tests/files/convert7a.gno index fa4fb6e43df..5de35bda8fa 100644 --- a/gnovm/tests/files/convert7a.gno +++ b/gnovm/tests/files/convert7a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/convert7a.gno:5:10: cannot convert constant of type Float64Kind to Int64Kind +// main/convert7a.gno:5:10: cannot convert constant of type Float64Kind to Int64Kind // TypeCheckError: -// main/files/convert7a.gno:5:16: cannot convert a (constant 1.5 of type float64) to type int64 +// main/convert7a.gno:5:16: cannot convert a (constant 1.5 of type float64) to type int64 diff --git a/gnovm/tests/files/convert7b.gno b/gnovm/tests/files/convert7b.gno index 4f82b6b2c2b..8546bf8f70d 100644 --- a/gnovm/tests/files/convert7b.gno +++ b/gnovm/tests/files/convert7b.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/convert7b.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type +// main/convert7b.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type // TypeCheckError: -// main/files/convert7b.gno:4:16: cannot convert 1.5 (untyped float constant) to type int64 +// main/convert7b.gno:4:16: cannot convert 1.5 (untyped float constant) to type int64 diff --git a/gnovm/tests/files/defer0.gno b/gnovm/tests/files/defer0.gno index 59cfdd0ea2e..bdfd611d5ce 100644 --- a/gnovm/tests/files/defer0.gno +++ b/gnovm/tests/files/defer0.gno @@ -42,4 +42,4 @@ func main() { // bye1 // TypeCheckError: -// main/files/defer0.gno:9:11: invalid operation: invalid use of ... with built-in println +// main/defer0.gno:9:11: invalid operation: invalid use of ... with built-in println diff --git a/gnovm/tests/files/float0.gno b/gnovm/tests/files/float0.gno index 751c0de73a8..84bf17a878d 100644 --- a/gnovm/tests/files/float0.gno +++ b/gnovm/tests/files/float0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/float0.gno:4:7: cannot convert (const (1.2 bigdec)) to integer type +// main/float0.gno:4:7: cannot convert (const (1.2 bigdec)) to integer type // TypeCheckError: -// main/files/float0.gno:4:11: cannot convert 1.2 (untyped float constant) to type int +// main/float0.gno:4:11: cannot convert 1.2 (untyped float constant) to type int diff --git a/gnovm/tests/files/for20.gno b/gnovm/tests/files/for20.gno index 540c0caf90a..a2a71ce487f 100644 --- a/gnovm/tests/files/for20.gno +++ b/gnovm/tests/files/for20.gno @@ -15,4 +15,4 @@ loop: // hey // TypeCheckError: -// main/files/for20.gno:6:1: label loop declared and not used +// main/for20.gno:6:1: label loop declared and not used diff --git a/gnovm/tests/files/for21.gno b/gnovm/tests/files/for21.gno index d74b84476e3..fd4a9b4afa2 100644 --- a/gnovm/tests/files/for21.gno +++ b/gnovm/tests/files/for21.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/for21.gno:7:17: continue statement out of place +// main/for21.gno:7:17: continue statement out of place // TypeCheckError: -// main/files/for21.gno:7:17: continue not in for statement +// main/for21.gno:7:17: continue not in for statement diff --git a/gnovm/tests/files/for22.gno b/gnovm/tests/files/for22.gno index b332dc17268..aef1942c18e 100644 --- a/gnovm/tests/files/for22.gno +++ b/gnovm/tests/files/for22.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/for22.gno:7:17: fallthrough statement out of place +// main/for22.gno:7:17: fallthrough statement out of place // TypeCheckError: -// main/files/for22.gno:7:17: fallthrough statement out of place +// main/for22.gno:7:17: fallthrough statement out of place diff --git a/gnovm/tests/files/for23.gno b/gnovm/tests/files/for23.gno index 69922dcdeb5..76a489a6f2e 100644 --- a/gnovm/tests/files/for23.gno +++ b/gnovm/tests/files/for23.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/for23.gno:7:17: break statement out of place +// main/for23.gno:7:17: break statement out of place // TypeCheckError: -// main/files/for23.gno:7:17: break not in for, switch, or select statement +// main/for23.gno:7:17: break not in for, switch, or select statement diff --git a/gnovm/tests/files/for24.gno b/gnovm/tests/files/for24.gno index 4bc13f08334..3945675bb7c 100644 --- a/gnovm/tests/files/for24.gno +++ b/gnovm/tests/files/for24.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/for24.gno:8:21: break statement out of place +// main/for24.gno:8:21: break statement out of place // TypeCheckError: -// main/files/for24.gno:8:21: break not in for, switch, or select statement +// main/for24.gno:8:21: break not in for, switch, or select statement diff --git a/gnovm/tests/files/for7.gno b/gnovm/tests/files/for7.gno index 2d4e7e94076..ea98a27aa76 100644 --- a/gnovm/tests/files/for7.gno +++ b/gnovm/tests/files/for7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/for7.gno:4:2: expected typed bool kind, but got IntKind +// main/for7.gno:4:2: expected typed bool kind, but got IntKind // TypeCheckError: -// main/files/for7.gno:4:14: non-boolean condition in for statement +// main/for7.gno:4:14: non-boolean condition in for statement diff --git a/gnovm/tests/files/fun21.gno b/gnovm/tests/files/fun21.gno index fcf4bc5897d..aa601eb1b26 100644 --- a/gnovm/tests/files/fun21.gno +++ b/gnovm/tests/files/fun21.gno @@ -9,9 +9,9 @@ func main() { } // Error: -// main/files/fun21.gno:4:2: expected 1 return values; got 0 +// main/fun21.gno:4:2: expected 1 return values; got 0 // TypeCheckError: -// main/files/fun21.gno:4:2: not enough return values +// main/fun21.gno:4:2: not enough return values // have () // want (string) diff --git a/gnovm/tests/files/fun22.gno b/gnovm/tests/files/fun22.gno index 805661fe605..694d2d2ebbf 100644 --- a/gnovm/tests/files/fun22.gno +++ b/gnovm/tests/files/fun22.gno @@ -7,9 +7,9 @@ func main() { } // Error: -// main/files/fun22.gno:6:2: wrong argument count in call to time.Date; want 8 got 0 +// main/fun22.gno:6:2: wrong argument count in call to time.Date; want 8 got 0 // TypeCheckError: -// main/files/fun22.gno:6:12: not enough arguments in call to time.Date +// main/fun22.gno:6:12: not enough arguments in call to time.Date // have () // want (int, time.Month, int, int, int, int, int, *time.Location) diff --git a/gnovm/tests/files/fun23.gno b/gnovm/tests/files/fun23.gno index 371c3818424..666864ce375 100644 --- a/gnovm/tests/files/fun23.gno +++ b/gnovm/tests/files/fun23.gno @@ -7,9 +7,9 @@ func main() { } // Error: -// main/files/fun23.gno:3:17: expected 0 return values; got 1 +// main/fun23.gno:3:17: expected 0 return values; got 1 // TypeCheckError: -// main/files/fun23.gno:3:24: too many return values +// main/fun23.gno:3:24: too many return values // have (int) // want () diff --git a/gnovm/tests/files/fun24.gno b/gnovm/tests/files/fun24.gno index 9fcca8d708d..3a94719b5e2 100644 --- a/gnovm/tests/files/fun24.gno +++ b/gnovm/tests/files/fun24.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/fun24.gno:3:28: cannot use untyped string as IntKind +// main/fun24.gno:3:28: cannot use untyped string as IntKind // TypeCheckError: -// main/files/fun24.gno:3:38: cannot use "foo" (untyped string constant) as int value in return statement +// main/fun24.gno:3:38: cannot use "foo" (untyped string constant) as int value in return statement diff --git a/gnovm/tests/files/fun25.gno b/gnovm/tests/files/fun25.gno index 0ec06e2ce75..e5e150b3828 100644 --- a/gnovm/tests/files/fun25.gno +++ b/gnovm/tests/files/fun25.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/fun25.gno:3:35: cannot use string as int +// main/fun25.gno:3:35: cannot use string as int // TypeCheckError: -// main/files/fun25.gno:3:42: cannot use x (variable of type string) as int value in return statement +// main/fun25.gno:3:42: cannot use x (variable of type string) as int value in return statement diff --git a/gnovm/tests/files/fun27.gno b/gnovm/tests/files/fun27.gno index 029deaec6e7..b5c8fd22e33 100644 --- a/gnovm/tests/files/fun27.gno +++ b/gnovm/tests/files/fun27.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/fun27.gno:8:2: bigint does not implement main.Foo (missing method foo) +// main/fun27.gno:8:2: bigint does not implement main.Foo (missing method foo) // TypeCheckError: -// main/files/fun27.gno:8:9: cannot use 1 (constant of type int) as Foo value in return statement: int does not implement Foo (missing method foo) +// main/fun27.gno:8:9: cannot use 1 (constant of type int) as Foo value in return statement: int does not implement Foo (missing method foo) diff --git a/gnovm/tests/files/fun28.gno b/gnovm/tests/files/fun28.gno index 703a28e927c..54745b56aac 100644 --- a/gnovm/tests/files/fun28.gno +++ b/gnovm/tests/files/fun28.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/fun28.gno:6:2: cannot use nil as int value in argument to f +// main/fun28.gno:6:2: cannot use nil as int value in argument to f // TypeCheckError: -// main/files/fun28.gno:6:4: cannot use nil as int value in argument to f +// main/fun28.gno:6:4: cannot use nil as int value in argument to f diff --git a/gnovm/tests/files/fun9.gno b/gnovm/tests/files/fun9.gno index 11e3c033d89..9b7ab6807d3 100644 --- a/gnovm/tests/files/fun9.gno +++ b/gnovm/tests/files/fun9.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// (1 main[main/files/fun9.gno:5:1].myint) +// (1 main[main/fun9.gno:5:1-9:2].myint) diff --git a/gnovm/tests/files/goto6.gno b/gnovm/tests/files/goto6.gno index 2c8e844ac9f..d9e5cc84d18 100644 --- a/gnovm/tests/files/goto6.gno +++ b/gnovm/tests/files/goto6.gno @@ -24,4 +24,4 @@ func main() { // there // TypeCheckError: -// main/files/goto6.gno:6:2: label nowhere declared and not used +// main/goto6.gno:6:2: label nowhere declared and not used diff --git a/gnovm/tests/files/govdao/realm_govdao.gno b/gnovm/tests/files/govdao/realm_govdao.gno index ca04ef7132c..984fbdb1be1 100644 --- a/gnovm/tests/files/govdao/realm_govdao.gno +++ b/gnovm/tests/files/govdao/realm_govdao.gno @@ -71,21 +71,5 @@ func Render() { println(dao.Render("")) } -// Output: -// true -// # Active Proposals: -// ## Proposal with id: 0 -// ### Title: Proposal Title: Dummy proposal -// -// ### Proposed by: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// Description: Do nothing -// -// -// ### Proposal Status: -// -// - **PROPOSAL HAS BEEN ACCEPTED** -// - Allowed tiers to vote: T1 T2 T3 -// - YES PERCENT: 66.66666666666666% -// - NO PERCENT: 0% -// - [Go to votes list](/r/gov/dao:0/votes). +// Error: +// gno.land/r/gov/dao/v3/memberstore/memberstore.gno:125:2: builtin identifiers cannot be shadowed: realm diff --git a/gnovm/tests/files/if2.gno b/gnovm/tests/files/if2.gno index 2152e7315cd..a312d04ba1c 100644 --- a/gnovm/tests/files/if2.gno +++ b/gnovm/tests/files/if2.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/if2.gno:7:2: expected typed bool kind, but got IntKind +// main/if2.gno:7:2: expected typed bool kind, but got IntKind // TypeCheckError: -// main/files/if2.gno:7:5: non-boolean condition in if statement +// main/if2.gno:7:5: non-boolean condition in if statement diff --git a/gnovm/tests/files/import10.gno b/gnovm/tests/files/import10.gno index ba1f2c37218..bfd425009b9 100644 --- a/gnovm/tests/files/import10.gno +++ b/gnovm/tests/files/import10.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/import10.gno:7:10: package fmt cannot only be referred to in a selector expression +// main/import10.gno:7:10: package fmt cannot only be referred to in a selector expression // TypeCheckError: -// main/files/import10.gno:7:10: use of package fmt not in selector +// main/import10.gno:7:10: use of package fmt not in selector diff --git a/gnovm/tests/files/import11.gno b/gnovm/tests/files/import11.gno index 594e9f10698..dd93d3443c9 100644 --- a/gnovm/tests/files/import11.gno +++ b/gnovm/tests/files/import11.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// gno.land/p/demo/bar/files/import11.gno:5:2: pure package path "gno.land/p/demo/bar" cannot import realm path "gno.land/r/demo/tests" +// gno.land/p/demo/bar/import11.gno:5:2: pure package path "gno.land/p/demo/bar" cannot import realm path "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/import12.gno b/gnovm/tests/files/import12.gno index a3f3fe4fbf6..43f7d3b3a15 100644 --- a/gnovm/tests/files/import12.gno +++ b/gnovm/tests/files/import12.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/files/import12.gno:6:2: cannot import stdlib internal/ package outside of standard library +// gno.land/p/demo/import12.gno:6:2: cannot import stdlib internal/ package outside of standard library diff --git a/gnovm/tests/files/import13.gno b/gnovm/tests/files/import13.gno index c0aa0e28a01..91ce598e4cc 100644 --- a/gnovm/tests/files/import13.gno +++ b/gnovm/tests/files/import13.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/files/import13.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" +// gno.land/p/demo/import13.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" diff --git a/gnovm/tests/files/import13b.gno b/gnovm/tests/files/import13b.gno index bedebb89b2f..3a77017d254 100644 --- a/gnovm/tests/files/import13b.gno +++ b/gnovm/tests/files/import13b.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/files/import13b.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" +// gno.land/p/demo/import13b.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" diff --git a/gnovm/tests/files/init1.gno b/gnovm/tests/files/init1.gno index 1b5493e8b41..3ef5dfd87b0 100644 --- a/gnovm/tests/files/init1.gno +++ b/gnovm/tests/files/init1.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/init1.gno:8:2: name init not declared +// main/init1.gno:8:2: name init not declared // TypeCheckError: -// main/files/init1.gno:8:2: undefined: init +// main/init1.gno:8:2: undefined: init diff --git a/gnovm/tests/files/interface47.gno b/gnovm/tests/files/interface47.gno index 2b00661e4bc..a89bf4c38fc 100644 --- a/gnovm/tests/files/interface47.gno +++ b/gnovm/tests/files/interface47.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/interface47.gno:13:10: main.Runner does not implement main.Swimmer (missing method Swim) +// main/interface47.gno:13:10: main.Runner does not implement main.Swimmer (missing method Swim) // TypeCheckError: -// main/files/interface47.gno:13:18: cannot convert a (variable of interface type Runner) to type Swimmer: Runner does not implement Swimmer (missing method Swim) +// main/interface47.gno:13:18: cannot convert a (variable of interface type Runner) to type Swimmer: Runner does not implement Swimmer (missing method Swim) diff --git a/gnovm/tests/files/invalid_labels0.gno b/gnovm/tests/files/invalid_labels0.gno index 65e072c9871..f7e78aaa93e 100644 --- a/gnovm/tests/files/invalid_labels0.gno +++ b/gnovm/tests/files/invalid_labels0.gno @@ -11,4 +11,4 @@ FirstLoop: } // Error: -// main/files/invalid_labels0.gno:9:3: cannot find branch label "FirstLoop" +// main/invalid_labels0.gno:9:3: cannot find branch label "FirstLoop" diff --git a/gnovm/tests/files/invalid_labels1.gno b/gnovm/tests/files/invalid_labels1.gno index 528a3066ac0..fa08d77e6a4 100644 --- a/gnovm/tests/files/invalid_labels1.gno +++ b/gnovm/tests/files/invalid_labels1.gno @@ -9,7 +9,7 @@ func undefinedLabel() { } // Error: -// files/invalid_labels1.gno:7:9: label UndefinedLabel undefined +// invalid_labels1.gno:7:9: label UndefinedLabel undefined // TypeCheckError: -// main/files/invalid_labels1.gno:7:9: invalid break label UndefinedLabel +// main/invalid_labels1.gno:7:9: invalid break label UndefinedLabel diff --git a/gnovm/tests/files/invalid_labels2.gno b/gnovm/tests/files/invalid_labels2.gno index b28cd05371a..ca6062f2f01 100644 --- a/gnovm/tests/files/invalid_labels2.gno +++ b/gnovm/tests/files/invalid_labels2.gno @@ -12,7 +12,7 @@ FirstLoop: } // Error: -// main/files/invalid_labels2.gno:7:3: cannot find branch label "FirstLoop" +// main/invalid_labels2.gno:7:3: cannot find branch label "FirstLoop" // TypeCheckError: -// main/files/invalid_labels2.gno:7:12: invalid continue label FirstLoop; main/files/invalid_labels2.gno:9:1: label FirstLoop declared and not used +// main/invalid_labels2.gno:7:12: invalid continue label FirstLoop; main/invalid_labels2.gno:9:1: label FirstLoop declared and not used diff --git a/gnovm/tests/files/invalid_labels3.gno b/gnovm/tests/files/invalid_labels3.gno index 00061e4efab..b7588aba767 100644 --- a/gnovm/tests/files/invalid_labels3.gno +++ b/gnovm/tests/files/invalid_labels3.gno @@ -9,7 +9,7 @@ func invalidLabelStatement() { } // Error: -// files/invalid_labels3.gno:7:9: label InvalidLabel undefined +// invalid_labels3.gno:7:9: label InvalidLabel undefined // TypeCheckError: -// main/files/invalid_labels3.gno:7:9: invalid break label InvalidLabel +// main/invalid_labels3.gno:7:9: invalid break label InvalidLabel diff --git a/gnovm/tests/files/issue_1096.gno b/gnovm/tests/files/issue_1096.gno index 86ae2820319..cbc8a74d5a9 100644 --- a/gnovm/tests/files/issue_1096.gno +++ b/gnovm/tests/files/issue_1096.gno @@ -397,4 +397,4 @@ func (_ Z) manip2(xs ...X) { // 0 // TypeCheckError: -// main/files/issue_1096.gno:134:2: cannot assign to xm[1].Array[1] (neither addressable nor a map index expression) +// main/issue_1096.gno:134:2: cannot assign to xm[1].Array[1] (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/len7.gno b/gnovm/tests/files/len7.gno index 3078a711f85..387bc0ba3e3 100644 --- a/gnovm/tests/files/len7.gno +++ b/gnovm/tests/files/len7.gno @@ -8,4 +8,4 @@ func main() { // unexpected type for len(): *int // TypeCheckError: -// main/files/len7.gno:4:14: invalid argument: new(int) (value of type *int) for built-in len +// main/len7.gno:4:14: invalid argument: new(int) (value of type *int) for built-in len diff --git a/gnovm/tests/files/len8.gno b/gnovm/tests/files/len8.gno index 3ba6b73fcb0..756b9b4f85c 100644 --- a/gnovm/tests/files/len8.gno +++ b/gnovm/tests/files/len8.gno @@ -10,4 +10,4 @@ func main() { // unexpected type for len(): struct{A int; B int} // TypeCheckError: -// main/files/len8.gno:4:14: invalid argument: struct{A, B int}{} (value of type struct{A int; B int}) for built-in len +// main/len8.gno:4:14: invalid argument: struct{A, B int}{} (value of type struct{A int; B int}) for built-in len diff --git a/gnovm/tests/files/map0.gno b/gnovm/tests/files/map0.gno index 0785ee47e38..7799617e765 100644 --- a/gnovm/tests/files/map0.gno +++ b/gnovm/tests/files/map0.gno @@ -12,4 +12,4 @@ func main() { // duplicate key "hello" in map literal // TypeCheckError: -// main/files/map0.gno:7:3: duplicate key "hello" in map literal; main/files/map0.gno:4:2: declared and not used: m +// main/map0.gno:7:3: duplicate key "hello" in map literal; main/map0.gno:4:2: declared and not used: m diff --git a/gnovm/tests/files/map1.gno b/gnovm/tests/files/map1.gno index ad9fb502df8..b47bef5e1ab 100644 --- a/gnovm/tests/files/map1.gno +++ b/gnovm/tests/files/map1.gno @@ -11,4 +11,4 @@ func main() { } // TypeCheckError: -// main/files/map1.gno:5:2: declared and not used: m +// main/map1.gno:5:2: declared and not used: m diff --git a/gnovm/tests/files/native0.gno b/gnovm/tests/files/native0.gno index a6b8f3e67bf..3b422473cfe 100644 --- a/gnovm/tests/files/native0.gno +++ b/gnovm/tests/files/native0.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/native0.gno:3:1: function invalidNative does not have a body but is not natively defined (did you build after pulling from the repository?) +// main/native0.gno:3:1: function invalidNative does not have a body but is not natively defined (did you build after pulling from the repository?) diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index c1479d2a17d..8321bc6bc24 100644 --- a/gnovm/tests/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/op7.gno:11:5: operator > not defined on: InterfaceKind +// main/op7.gno:11:5: operator > not defined on: InterfaceKind // TypeCheckError: -// main/files/op7.gno:11:5: invalid operation: err > invalidT (operator > not defined on interface) +// main/op7.gno:11:5: invalid operation: err > invalidT (operator > not defined on interface) diff --git a/gnovm/tests/files/overflow10.gno b/gnovm/tests/files/overflow10.gno index 3fdf9df8bf2..061feb1130c 100644 --- a/gnovm/tests/files/overflow10.gno +++ b/gnovm/tests/files/overflow10.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow10.gno:3:1: constant overflows +// main/overflow10.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow10.gno:4:13: int64(1) << 65 (constant 36893488147419103232 of type int64) overflows int64 +// main/overflow10.gno:4:13: int64(1) << 65 (constant 36893488147419103232 of type int64) overflows int64 diff --git a/gnovm/tests/files/overflow11.gno b/gnovm/tests/files/overflow11.gno index f103a833a71..93bd4fc7c75 100644 --- a/gnovm/tests/files/overflow11.gno +++ b/gnovm/tests/files/overflow11.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow11.gno:3:1: constant overflows +// main/overflow11.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow11.gno:4:13: uint8(1) << 8 (constant 256 of type uint8) overflows uint8 +// main/overflow11.gno:4:13: uint8(1) << 8 (constant 256 of type uint8) overflows uint8 diff --git a/gnovm/tests/files/overflow12.gno b/gnovm/tests/files/overflow12.gno index 3e5c851be0d..4c19c35903b 100644 --- a/gnovm/tests/files/overflow12.gno +++ b/gnovm/tests/files/overflow12.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow12.gno:3:1: constant overflows +// main/overflow12.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow12.gno:4:16: uint16(1) << 16 (constant 65536 of type uint16) overflows uint16 +// main/overflow12.gno:4:16: uint16(1) << 16 (constant 65536 of type uint16) overflows uint16 diff --git a/gnovm/tests/files/overflow13.gno b/gnovm/tests/files/overflow13.gno index fd7352b1d21..07f6c166f7b 100644 --- a/gnovm/tests/files/overflow13.gno +++ b/gnovm/tests/files/overflow13.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow13.gno:3:1: constant overflows +// main/overflow13.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow13.gno:4:13: uint32(1) << 33 (constant 8589934592 of type uint32) overflows uint32 +// main/overflow13.gno:4:13: uint32(1) << 33 (constant 8589934592 of type uint32) overflows uint32 diff --git a/gnovm/tests/files/overflow14.gno b/gnovm/tests/files/overflow14.gno index 0ddaaa6a7d6..62324d1802a 100644 --- a/gnovm/tests/files/overflow14.gno +++ b/gnovm/tests/files/overflow14.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow14.gno:3:1: constant overflows +// main/overflow14.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow14.gno:4:16: uint64(1) << 65 (constant 36893488147419103232 of type uint64) overflows uint64 +// main/overflow14.gno:4:16: uint64(1) << 65 (constant 36893488147419103232 of type uint64) overflows uint64 diff --git a/gnovm/tests/files/overflow16.gno b/gnovm/tests/files/overflow16.gno index 96f69dbc495..16c5abe5365 100644 --- a/gnovm/tests/files/overflow16.gno +++ b/gnovm/tests/files/overflow16.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/overflow16.gno:5:2: bigint overflows target kind +// main/overflow16.gno:5:2: bigint overflows target kind // TypeCheckError: -// main/files/overflow16.gno:5:10: cannot use c1 (untyped int constant 340282366920938463463374607431768211456) as int value in argument to built-in println (overflows) +// main/overflow16.gno:5:10: cannot use c1 (untyped int constant 340282366920938463463374607431768211456) as int value in argument to built-in println (overflows) diff --git a/gnovm/tests/files/overflow6.gno b/gnovm/tests/files/overflow6.gno index 7cb9d735bf0..e8fcc3aa425 100644 --- a/gnovm/tests/files/overflow6.gno +++ b/gnovm/tests/files/overflow6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow6.gno:3:1: constant overflows +// main/overflow6.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow6.gno:4:12: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 +// main/overflow6.gno:4:12: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 diff --git a/gnovm/tests/files/overflow7.gno b/gnovm/tests/files/overflow7.gno index 67bb88bd557..b8547729e49 100644 --- a/gnovm/tests/files/overflow7.gno +++ b/gnovm/tests/files/overflow7.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow7.gno:3:1: constant overflows +// main/overflow7.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow7.gno:4:13: int8(1) << 8 (constant 256 of type int8) overflows int8 +// main/overflow7.gno:4:13: int8(1) << 8 (constant 256 of type int8) overflows int8 diff --git a/gnovm/tests/files/overflow8.gno b/gnovm/tests/files/overflow8.gno index 8fa549b8c23..0f039d2fce6 100644 --- a/gnovm/tests/files/overflow8.gno +++ b/gnovm/tests/files/overflow8.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow8.gno:3:1: constant overflows +// main/overflow8.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow8.gno:4:13: int16(1) << 16 (constant 65536 of type int16) overflows int16 +// main/overflow8.gno:4:13: int16(1) << 16 (constant 65536 of type int16) overflows int16 diff --git a/gnovm/tests/files/overflow9.gno b/gnovm/tests/files/overflow9.gno index 686dc799ee3..1e7c892893b 100644 --- a/gnovm/tests/files/overflow9.gno +++ b/gnovm/tests/files/overflow9.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/overflow9.gno:3:1: constant overflows +// main/overflow9.gno:3:1: constant overflows // TypeCheckError: -// main/files/overflow9.gno:4:13: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 +// main/overflow9.gno:4:13: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 diff --git a/gnovm/tests/files/panic0.gno b/gnovm/tests/files/panic0.gno index 06460ca9d07..b4813ea76b0 100644 --- a/gnovm/tests/files/panic0.gno +++ b/gnovm/tests/files/panic0.gno @@ -7,7 +7,7 @@ func main() { // Stacktrace: // panic: wtf // main() -// main/files/panic0.gno:4 +// main/panic0.gno:4 // Error: // wtf diff --git a/gnovm/tests/files/panic0a.gno b/gnovm/tests/files/panic0a.gno index 5adfc8a1465..fad9596d26b 100644 --- a/gnovm/tests/files/panic0a.gno +++ b/gnovm/tests/files/panic0a.gno @@ -37,9 +37,9 @@ func main() { // Stacktrace: // panic: wtf // f(v.((const-type int)),lit[0],*pit,&vit<~VPBlock(1,0)>,!b,[](const-type string),typeval{main.S},map[(const-type string)] (const-type string),func(s (const-type string)) .res.0 (const-type string){ ... }) -// main/files/panic0a.gno:9 +// main/panic0a.gno:9 // main() -// main/files/panic0a.gno:22 +// main/panic0a.gno:22 // Error: // wtf diff --git a/gnovm/tests/files/panic0b.gno b/gnovm/tests/files/panic0b.gno index 71983bc2aca..9e40fe4fc32 100644 --- a/gnovm/tests/files/panic0b.gno +++ b/gnovm/tests/files/panic0b.gno @@ -17,17 +17,17 @@ func f() { // Stacktrace: // panic: first // f() -// main/files/panic0b.gno:14 +// main/panic0b.gno:14 // main() -// main/files/panic0b.gno:4 +// main/panic0b.gno:4 // ... 1 panic(s) elided ... // panic: third // defer func(){ ... }() -// main/files/panic0b.gno:9 +// main/panic0b.gno:9 // f() -// main/files/panic0b.gno:8 +// main/panic0b.gno:8 // main() -// main/files/panic0b.gno:4 +// main/panic0b.gno:4 // Error: // first diff --git a/gnovm/tests/files/panic0c.gno b/gnovm/tests/files/panic0c.gno index c331ee3bd17..324b3d8d997 100644 --- a/gnovm/tests/files/panic0c.gno +++ b/gnovm/tests/files/panic0c.gno @@ -79,9 +79,9 @@ func main() { // Stacktrace: // panic: wtf // f(a,true,0,1,1,1,1,1,1,1,1,1,1,1,1,strs,st,m,t) -// main/files/panic0c.gno:28 +// main/panic0c.gno:28 // main() -// main/files/panic0c.gno:57 +// main/panic0c.gno:57 // Error: // wtf diff --git a/gnovm/tests/files/panic1.gno b/gnovm/tests/files/panic1.gno index 91e127c7200..d2bc882fbff 100644 --- a/gnovm/tests/files/panic1.gno +++ b/gnovm/tests/files/panic1.gno @@ -25,10 +25,10 @@ func main() { // Stacktrace: // panic: here // main() -// main/files/panic1.gno:22 +// main/panic1.gno:22 // Error: // here // TypeCheckError: -// main/files/panic1.gno:21:2: declared and not used: test +// main/panic1.gno:21:2: declared and not used: test diff --git a/gnovm/tests/files/panic2a.gno b/gnovm/tests/files/panic2a.gno index 7310d6cce71..b2ff20d7b7c 100644 --- a/gnovm/tests/files/panic2a.gno +++ b/gnovm/tests/files/panic2a.gno @@ -14,262 +14,262 @@ func main() { // Stacktrace: // panic: here // p(i + 1) -// main/files/panic2a.gno:5 +// main/panic2a.gno:5 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // ...74 frame(s) elided... // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(i + 1) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // p(0) -// main/files/panic2a.gno:7 +// main/panic2a.gno:7 // main() -// main/files/panic2a.gno:11 +// main/panic2a.gno:11 // Error: // here diff --git a/gnovm/tests/files/panic2b.gno b/gnovm/tests/files/panic2b.gno index 225800587fb..2f8b4445714 100644 --- a/gnovm/tests/files/panic2b.gno +++ b/gnovm/tests/files/panic2b.gno @@ -17,25 +17,25 @@ func main() { // Stacktrace: // panic: here // p(i + 1) -// main/files/panic2b.gno:8 +// main/panic2b.gno:8 // p(i + 1) -// main/files/panic2b.gno:10 +// main/panic2b.gno:10 // p(i + 1) -// main/files/panic2b.gno:10 +// main/panic2b.gno:10 // p(i + 1) -// main/files/panic2b.gno:10 +// main/panic2b.gno:10 // p(0) -// main/files/panic2b.gno:10 +// main/panic2b.gno:10 // main() -// main/files/panic2b.gno:14 +// main/panic2b.gno:14 // ... 4 panic(s) elided ... // panic: here // defer func(){ ... }() -// main/files/panic2b.gno:5 +// main/panic2b.gno:5 // p(0) -// main/files/panic2b.gno:4 +// main/panic2b.gno:4 // main() -// main/files/panic2b.gno:14 +// main/panic2b.gno:14 // Error: // here diff --git a/gnovm/tests/files/parse_err0.gno b/gnovm/tests/files/parse_err0.gno index 2e428953942..98e5cb15e36 100644 --- a/gnovm/tests/files/parse_err0.gno +++ b/gnovm/tests/files/parse_err0.gno @@ -7,7 +7,7 @@ func () A() func main() {} // Error: -// files/parse_err0.gno:5:1: method has no receiver +// parse_err0.gno:5:1: method has no receiver // TypeCheckError: -// main/files/parse_err0.gno:5:6: method has no receiver +// main/parse_err0.gno:5:6: method has no receiver diff --git a/gnovm/tests/files/parse_err1.gno b/gnovm/tests/files/parse_err1.gno index d2b79226125..6fa57ab0060 100644 --- a/gnovm/tests/files/parse_err1.gno +++ b/gnovm/tests/files/parse_err1.gno @@ -13,7 +13,7 @@ func (n *node) foo(targ, wndex int) { func main() {} // Error: -// files/parse_err1.gno:10:6: invalid operation: more than one index +// parse_err1.gno:10:6: invalid operation: more than one index // TypeCheckError: -// main/files/parse_err1.gno:10:16: invalid operation: more than one index +// main/parse_err1.gno:10:16: invalid operation: more than one index diff --git a/gnovm/tests/files/parse_err2.gno b/gnovm/tests/files/parse_err2.gno index 9c711cff1fe..bfdcd21974f 100644 --- a/gnovm/tests/files/parse_err2.gno +++ b/gnovm/tests/files/parse_err2.gno @@ -13,4 +13,4 @@ func TestAdd(t *testing.T) { } // Error: -// files/parse_err2.gno:12:2: goroutines are not permitted +// parse_err2.gno:12:2: goroutines are not permitted diff --git a/gnovm/tests/files/pkgname1.gno b/gnovm/tests/files/pkgname1.gno index 4e31f5dc9ed..e7d1edd367d 100644 --- a/gnovm/tests/files/pkgname1.gno +++ b/gnovm/tests/files/pkgname1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/pkgname1.gno:5:2: package name for "github.com/gnolang/gno/_test/bar" ("quux") doesn't match its expected identifier "bar"; the import declaration must specify an identifier +// main/pkgname1.gno:5:2: package name for "github.com/gnolang/gno/_test/bar" ("quux") doesn't match its expected identifier "bar"; the import declaration must specify an identifier // TypeCheckError: -// main/files/pkgname1.gno:9:19: undefined: bar; main/files/pkgname1.gno:5:2: "github.com/gnolang/gno/_test/bar" imported as quux and not used +// main/pkgname1.gno:9:19: undefined: bar; main/pkgname1.gno:5:2: "github.com/gnolang/gno/_test/bar" imported as quux and not used diff --git a/gnovm/tests/files/ptr10.gno b/gnovm/tests/files/ptr10.gno index 2ef6346553a..27b58f898b2 100644 --- a/gnovm/tests/files/ptr10.gno +++ b/gnovm/tests/files/ptr10.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/ptr10.gno:4:10: invalid operation: cannot indirect nil +// main/ptr10.gno:4:10: invalid operation: cannot indirect nil // TypeCheckError: -// main/files/ptr10.gno:4:11: invalid operation: cannot indirect nil +// main/ptr10.gno:4:11: invalid operation: cannot indirect nil diff --git a/gnovm/tests/files/ptr9.gno b/gnovm/tests/files/ptr9.gno index e5075fb6fc0..2998a1c1481 100644 --- a/gnovm/tests/files/ptr9.gno +++ b/gnovm/tests/files/ptr9.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/ptr9.gno:5:10: invalid operation: cannot indirect v (variable of type int) +// main/ptr9.gno:5:10: invalid operation: cannot indirect v (variable of type int) // TypeCheckError: -// main/files/ptr9.gno:5:11: invalid operation: cannot indirect v (variable of type int) +// main/ptr9.gno:5:11: invalid operation: cannot indirect v (variable of type int) diff --git a/gnovm/tests/files/range8.gno b/gnovm/tests/files/range8.gno index 63698dd58e9..12dfbe0cd03 100644 --- a/gnovm/tests/files/range8.gno +++ b/gnovm/tests/files/range8.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/range8.gno:4:2: cannot range over nil +// main/range8.gno:4:2: cannot range over nil // TypeCheckError: -// main/files/range8.gno:4:20: cannot range over nil +// main/range8.gno:4:20: cannot range over nil diff --git a/gnovm/tests/files/recover10.gno b/gnovm/tests/files/recover10.gno index de083a322a4..4f233b50ff3 100644 --- a/gnovm/tests/files/recover10.gno +++ b/gnovm/tests/files/recover10.gno @@ -9,7 +9,7 @@ func main() { // Stacktrace: // panic: ahhhhh // main() -// main/files/recover10.gno:6 +// main/recover10.gno:6 // Error: // ahhhhh diff --git a/gnovm/tests/files/recover13.gno b/gnovm/tests/files/recover13.gno index 3f3d5053ac0..6b8bfaa754a 100644 --- a/gnovm/tests/files/recover13.gno +++ b/gnovm/tests/files/recover13.gno @@ -15,4 +15,4 @@ func main() { // recover: invalid slice index -1 (index must be non-negative) // TypeCheckError: -// main/files/recover13.gno:11:13: invalid argument: index -1 (constant of type int) must not be negative +// main/recover13.gno:11:13: invalid argument: index -1 (constant of type int) must not be negative diff --git a/gnovm/tests/files/recover16.gno b/gnovm/tests/files/recover16.gno index 50ed4473a79..09dc22db9b7 100644 --- a/gnovm/tests/files/recover16.gno +++ b/gnovm/tests/files/recover16.gno @@ -14,4 +14,4 @@ func main() { // recover: len out of range // TypeCheckError: -// main/files/recover16.gno:10:21: invalid argument: index -1 (constant of type int) must not be negative +// main/recover16.gno:10:21: invalid argument: index -1 (constant of type int) must not be negative diff --git a/gnovm/tests/files/recover1b.gno b/gnovm/tests/files/recover1b.gno index 992be389e18..58a40c0478f 100644 --- a/gnovm/tests/files/recover1b.gno +++ b/gnovm/tests/files/recover1b.gno @@ -13,12 +13,12 @@ func main() { // Stacktrace: // panic: other panic // defer func(){ ... }() -// main/files/recover1b.gno:8 +// main/recover1b.gno:8 // main() -// main/files/recover1b.gno:6 +// main/recover1b.gno:6 // Error: // other panic // TypeCheckError: -// main/files/recover1b.gno:3:8: "fmt" imported and not used +// main/recover1b.gno:3:8: "fmt" imported and not used diff --git a/gnovm/tests/files/recover20.gno b/gnovm/tests/files/recover20.gno index 58e5191d910..ffa4436c16b 100644 --- a/gnovm/tests/files/recover20.gno +++ b/gnovm/tests/files/recover20.gno @@ -13,4 +13,4 @@ func main() { // Stacktrace: // panic: nil pointer dereference // main() -// main/files/recover20.gno:5 +// main/recover20.gno:5 diff --git a/gnovm/tests/files/recover8.gno b/gnovm/tests/files/recover8.gno index 8ee5a1f4e9c..561b2745ef3 100644 --- a/gnovm/tests/files/recover8.gno +++ b/gnovm/tests/files/recover8.gno @@ -23,11 +23,11 @@ func main() { // Stacktrace: // panic: do something panic // defer func(){ ... }() -// main/files/recover8.gno:7 +// main/recover8.gno:7 // doSomething() -// main/files/recover8.gno:4 +// main/recover8.gno:4 // main() -// main/files/recover8.gno:20 +// main/recover8.gno:20 // Error: // do something panic diff --git a/gnovm/tests/files/recursive1.gno b/gnovm/tests/files/recursive1.gno index bfd3e0ebaa0..4fd477b11a3 100644 --- a/gnovm/tests/files/recursive1.gno +++ b/gnovm/tests/files/recursive1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/recursive1.gno:3:6: invalid recursive type: S -> S +// main/recursive1.gno:3:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive1.gno:3:6: invalid recursive type: S refers to itself +// main/recursive1.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1c.gno b/gnovm/tests/files/recursive1c.gno index 37a2d9d4d7c..16ad2402dfc 100644 --- a/gnovm/tests/files/recursive1c.gno +++ b/gnovm/tests/files/recursive1c.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/recursive1c.gno:5:6: invalid recursive type: S -> S +// main/recursive1c.gno:5:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive1c.gno:5:6: invalid recursive type: S refers to itself +// main/recursive1c.gno:5:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1d.gno b/gnovm/tests/files/recursive1d.gno index ecccd9f90e9..f9cab595095 100644 --- a/gnovm/tests/files/recursive1d.gno +++ b/gnovm/tests/files/recursive1d.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/recursive1d.gno:5:6: invalid recursive type: S -> S +// main/recursive1d.gno:5:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive1d.gno:5:6: invalid recursive type: S refers to itself +// main/recursive1d.gno:5:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1e.gno b/gnovm/tests/files/recursive1e.gno index b04e82f9f99..875ac6a2893 100644 --- a/gnovm/tests/files/recursive1e.gno +++ b/gnovm/tests/files/recursive1e.gno @@ -13,4 +13,4 @@ func main() { // (struct{(array[(nil []main.S),(nil []main.S)] [2][]main.S)} main.S) // TypeCheckError: -// main/files/recursive1e.gno:8:9: declared and not used: b +// main/recursive1e.gno:8:9: declared and not used: b diff --git a/gnovm/tests/files/recursive1f.gno b/gnovm/tests/files/recursive1f.gno index 41be4957b89..65fb88644e3 100644 --- a/gnovm/tests/files/recursive1f.gno +++ b/gnovm/tests/files/recursive1f.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/recursive1f.gno:4:7: invalid recursive type: S -> S +// main/recursive1f.gno:4:7: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive1f.gno:4:7: invalid recursive type: S refers to itself +// main/recursive1f.gno:4:7: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive2.gno b/gnovm/tests/files/recursive2.gno index e995c68201e..3967e6f90f6 100644 --- a/gnovm/tests/files/recursive2.gno +++ b/gnovm/tests/files/recursive2.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/files/recursive2.gno:3:6: invalid recursive type: A -> B -> C -> A +// main/recursive2.gno:3:6: invalid recursive type: A -> B -> C -> A // TypeCheckError: -// main/files/recursive2.gno:3:6: invalid recursive type A; main/files/recursive2.gno:3:6: A refers to B; main/files/recursive2.gno:7:6: B refers to C; main/files/recursive2.gno:11:6: C refers to A +// main/recursive2.gno:3:6: invalid recursive type A; main/recursive2.gno:3:6: A refers to B; main/recursive2.gno:7:6: B refers to C; main/recursive2.gno:11:6: C refers to A diff --git a/gnovm/tests/files/recursive2c.gno b/gnovm/tests/files/recursive2c.gno index 868e3b137ed..1c7ec961c01 100644 --- a/gnovm/tests/files/recursive2c.gno +++ b/gnovm/tests/files/recursive2c.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/files/recursive2c.gno:4:7: name B not defined in fileset with files [files/recursive2c.gno] +// main/recursive2c.gno:4:7: name B not defined in fileset with files [recursive2c.gno] // TypeCheckError: -// main/files/recursive2c.gno:5:5: undefined: B; main/files/recursive2c.gno:9:5: undefined: C +// main/recursive2c.gno:5:5: undefined: B; main/recursive2c.gno:9:5: undefined: C diff --git a/gnovm/tests/files/recursive4a.gno b/gnovm/tests/files/recursive4a.gno index 4c1d0996c50..ef5323faa3c 100644 --- a/gnovm/tests/files/recursive4a.gno +++ b/gnovm/tests/files/recursive4a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/recursive4a.gno:3:6: invalid recursive type: time -> time +// main/recursive4a.gno:3:6: invalid recursive type: time -> time // TypeCheckError: -// main/files/recursive4a.gno:3:6: invalid recursive type: time refers to itself +// main/recursive4a.gno:3:6: invalid recursive type: time refers to itself diff --git a/gnovm/tests/files/recursive5.gno b/gnovm/tests/files/recursive5.gno index 166fbe826a4..468fa4627b8 100644 --- a/gnovm/tests/files/recursive5.gno +++ b/gnovm/tests/files/recursive5.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/recursive5.gno:3:6: invalid recursive type: S -> S +// main/recursive5.gno:3:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive5.gno:3:6: invalid recursive type: S refers to itself +// main/recursive5.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive6a.gno b/gnovm/tests/files/recursive6a.gno index c498b9738e7..5ecff3d6bc3 100644 --- a/gnovm/tests/files/recursive6a.gno +++ b/gnovm/tests/files/recursive6a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/recursive6a.gno:3:6: invalid recursive type: SelfReferencing -> SelfReferencing +// main/recursive6a.gno:3:6: invalid recursive type: SelfReferencing -> SelfReferencing // TypeCheckError: -// main/files/recursive6a.gno:3:6: invalid recursive type: SelfReferencing refers to itself +// main/recursive6a.gno:3:6: invalid recursive type: SelfReferencing refers to itself diff --git a/gnovm/tests/files/recursive7a.gno b/gnovm/tests/files/recursive7a.gno index a4c0b648111..d09c956bc28 100644 --- a/gnovm/tests/files/recursive7a.gno +++ b/gnovm/tests/files/recursive7a.gno @@ -5,7 +5,7 @@ type S [2]S func main() {} // Error: -// main/files/recursive7a.gno:3:6: invalid recursive type: S -> S +// main/recursive7a.gno:3:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive7a.gno:3:6: invalid recursive type: S refers to itself +// main/recursive7a.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive8.gno b/gnovm/tests/files/recursive8.gno index 007ef805aa9..e719a09adb9 100644 --- a/gnovm/tests/files/recursive8.gno +++ b/gnovm/tests/files/recursive8.gno @@ -5,7 +5,7 @@ type Int Int func main() {} // Error: -// main/files/recursive8.gno:3:6: invalid recursive type: Int -> Int +// main/recursive8.gno:3:6: invalid recursive type: Int -> Int // TypeCheckError: -// main/files/recursive8.gno:3:6: invalid recursive type: Int refers to itself +// main/recursive8.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9.gno b/gnovm/tests/files/recursive9.gno index 4f7c8c7ac13..f89f7eef0b6 100644 --- a/gnovm/tests/files/recursive9.gno +++ b/gnovm/tests/files/recursive9.gno @@ -5,7 +5,7 @@ type Int = Int func main() {} // Error: -// main/files/recursive9.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9.gno:3:6: invalid recursive type: Int -> Int // TypeCheckError: -// main/files/recursive9.gno:3:6: invalid recursive type: Int refers to itself +// main/recursive9.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9a.gno b/gnovm/tests/files/recursive9a.gno index b9803f70adb..0fd1ad1580b 100644 --- a/gnovm/tests/files/recursive9a.gno +++ b/gnovm/tests/files/recursive9a.gno @@ -5,7 +5,7 @@ type Int = *Int func main() {} // Error: -// main/files/recursive9a.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9a.gno:3:6: invalid recursive type: Int -> Int // TypeCheckError: -// main/files/recursive9a.gno:3:6: invalid recursive type: Int refers to itself +// main/recursive9a.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9b.gno b/gnovm/tests/files/recursive9b.gno index 8c34df37e52..f5aedc9475c 100644 --- a/gnovm/tests/files/recursive9b.gno +++ b/gnovm/tests/files/recursive9b.gno @@ -5,7 +5,7 @@ type Int = func() Int func main() {} // Error: -// main/files/recursive9b.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9b.gno:3:6: invalid recursive type: Int -> Int // TypeCheckError: -// main/files/recursive9b.gno:3:6: invalid recursive type: Int refers to itself +// main/recursive9b.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9c.gno b/gnovm/tests/files/recursive9c.gno index f6a41bbe51c..dc2cec3d403 100644 --- a/gnovm/tests/files/recursive9c.gno +++ b/gnovm/tests/files/recursive9c.gno @@ -5,7 +5,7 @@ type Int = []Int func main() {} // Error: -// main/files/recursive9c.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9c.gno:3:6: invalid recursive type: Int -> Int // TypeCheckError: -// main/files/recursive9c.gno:3:6: invalid recursive type: Int refers to itself +// main/recursive9c.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9d.gno b/gnovm/tests/files/recursive9d.gno index 43562a92520..f0823322c15 100644 --- a/gnovm/tests/files/recursive9d.gno +++ b/gnovm/tests/files/recursive9d.gno @@ -7,7 +7,7 @@ type S = struct { func main() {} // Error: -// main/files/recursive9d.gno:3:6: invalid recursive type: S -> S +// main/recursive9d.gno:3:6: invalid recursive type: S -> S // TypeCheckError: -// main/files/recursive9d.gno:3:6: invalid recursive type: S refers to itself +// main/recursive9d.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/redeclaration0.gno b/gnovm/tests/files/redeclaration0.gno index 710f1213072..f0f6f67eca7 100644 --- a/gnovm/tests/files/redeclaration0.gno +++ b/gnovm/tests/files/redeclaration0.gno @@ -11,8 +11,8 @@ func main() { } // Error: -// files/redeclaration0.gno:8:6: foo redeclared in this block -// previous declaration at files/redeclaration0.gno:4:7 +// redeclaration0.gno:8:6: foo redeclared in this block +// previous declaration at redeclaration0.gno:4:7 // TypeCheckError: -// main/files/redeclaration0.gno:8:6: foo redeclared in this block; main/files/redeclaration0.gno:4:7: other declaration of foo; main/files/redeclaration0.gno:9:2: foo (type) is not an expression; main/files/redeclaration0.gno:10:10: foo (type) is not an expression +// main/redeclaration0.gno:8:6: foo redeclared in this block; main/redeclaration0.gno:4:7: other declaration of foo; main/redeclaration0.gno:9:2: foo (type) is not an expression; main/redeclaration0.gno:10:10: foo (type) is not an expression diff --git a/gnovm/tests/files/redeclaration1.gno b/gnovm/tests/files/redeclaration1.gno index cd63b150b89..ca776435817 100644 --- a/gnovm/tests/files/redeclaration1.gno +++ b/gnovm/tests/files/redeclaration1.gno @@ -9,8 +9,8 @@ func main() { } // Error: -// files/redeclaration1.gno:6:6: foo redeclared in this block -// previous declaration at files/redeclaration1.gno:4:6 +// redeclaration1.gno:6:6: foo redeclared in this block +// previous declaration at redeclaration1.gno:4:6 // TypeCheckError: -// main/files/redeclaration1.gno:6:6: foo redeclared in this block; main/files/redeclaration1.gno:4:6: other declaration of foo; main/files/redeclaration1.gno:7:8: cannot use 2 (untyped int constant) as string value in assignment +// main/redeclaration1.gno:6:6: foo redeclared in this block; main/redeclaration1.gno:4:6: other declaration of foo; main/redeclaration1.gno:7:8: cannot use 2 (untyped int constant) as string value in assignment diff --git a/gnovm/tests/files/redeclaration2.gno b/gnovm/tests/files/redeclaration2.gno index 7ff2bec0b57..c178e4607f2 100644 --- a/gnovm/tests/files/redeclaration2.gno +++ b/gnovm/tests/files/redeclaration2.gno @@ -11,8 +11,8 @@ func main() { } // Error: -// files/redeclaration2.gno:8:6: foo redeclared in this block -// previous declaration at files/redeclaration2.gno:4:6 +// redeclaration2.gno:8:6: foo redeclared in this block +// previous declaration at redeclaration2.gno:4:6 // TypeCheckError: -// main/files/redeclaration2.gno:8:6: foo redeclared in this block; main/files/redeclaration2.gno:4:6: other declaration of foo; main/files/redeclaration2.gno:9:8: cannot use 2 (untyped int constant) as struct{yolo string} value in assignment +// main/redeclaration2.gno:8:6: foo redeclared in this block; main/redeclaration2.gno:4:6: other declaration of foo; main/redeclaration2.gno:9:8: cannot use 2 (untyped int constant) as struct{yolo string} value in assignment diff --git a/gnovm/tests/files/redeclaration3.gno b/gnovm/tests/files/redeclaration3.gno index 8105132e688..b0bec6fdb92 100644 --- a/gnovm/tests/files/redeclaration3.gno +++ b/gnovm/tests/files/redeclaration3.gno @@ -10,8 +10,8 @@ func main() { } // Error: -// files/redeclaration3.gno:7:7: foo redeclared in this block -// previous declaration at files/redeclaration3.gno:4:6 +// redeclaration3.gno:7:7: foo redeclared in this block +// previous declaration at redeclaration3.gno:4:6 // TypeCheckError: -// main/files/redeclaration3.gno:7:7: foo redeclared in this block; main/files/redeclaration3.gno:4:6: other declaration of foo; main/files/redeclaration3.gno:8:10: foo is not a type +// main/redeclaration3.gno:7:7: foo redeclared in this block; main/redeclaration3.gno:4:6: other declaration of foo; main/redeclaration3.gno:8:10: foo is not a type diff --git a/gnovm/tests/files/redeclaration4.gno b/gnovm/tests/files/redeclaration4.gno index ee1e067a3dd..7c8c2bca797 100644 --- a/gnovm/tests/files/redeclaration4.gno +++ b/gnovm/tests/files/redeclaration4.gno @@ -11,8 +11,8 @@ func main() { } // Error: -// files/redeclaration4.gno:8:7: foo redeclared in this block -// previous declaration at files/redeclaration4.gno:4:6 +// redeclaration4.gno:8:7: foo redeclared in this block +// previous declaration at redeclaration4.gno:4:6 // TypeCheckError: -// main/files/redeclaration4.gno:8:7: foo redeclared in this block; main/files/redeclaration4.gno:4:6: other declaration of foo; main/files/redeclaration4.gno:9:10: foo is not a type +// main/redeclaration4.gno:8:7: foo redeclared in this block; main/redeclaration4.gno:4:6: other declaration of foo; main/redeclaration4.gno:9:10: foo is not a type diff --git a/gnovm/tests/files/redeclaration5.gno b/gnovm/tests/files/redeclaration5.gno index 25cd562971e..7580813e6a6 100644 --- a/gnovm/tests/files/redeclaration5.gno +++ b/gnovm/tests/files/redeclaration5.gno @@ -11,8 +11,8 @@ func main() { } // Error: -// files/redeclaration5.gno:8:7: foo redeclared in this block -// previous declaration at files/redeclaration5.gno:4:7 +// redeclaration5.gno:8:7: foo redeclared in this block +// previous declaration at redeclaration5.gno:4:7 // TypeCheckError: -// main/files/redeclaration5.gno:8:7: foo redeclared in this block; main/files/redeclaration5.gno:4:7: other declaration of foo +// main/redeclaration5.gno:8:7: foo redeclared in this block; main/redeclaration5.gno:4:7: other declaration of foo diff --git a/gnovm/tests/files/redeclaration7.gno b/gnovm/tests/files/redeclaration7.gno index d987a58d7eb..8aef876dd48 100644 --- a/gnovm/tests/files/redeclaration7.gno +++ b/gnovm/tests/files/redeclaration7.gno @@ -9,5 +9,5 @@ func main() { } // Error: -// files/redeclaration7.gno:5:6: f1 redeclared in this block -// previous declaration at files/redeclaration7.gno:3:6 +// redeclaration7.gno:5:6: f1 redeclared in this block +// previous declaration at redeclaration7.gno:3:6 diff --git a/gnovm/tests/files/redeclaration9.gno b/gnovm/tests/files/redeclaration9.gno index 76f887acce8..5927f0cdb71 100644 --- a/gnovm/tests/files/redeclaration9.gno +++ b/gnovm/tests/files/redeclaration9.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/redeclaration9.gno:7:1: redeclaration of method a.method +// main/redeclaration9.gno:7:1: redeclaration of method a.method // TypeCheckError: -// main/files/redeclaration9.gno:7:12: method a.method already declared at main/files/redeclaration9.gno:5:12 +// main/redeclaration9.gno:7:12: method a.method already declared at main/redeclaration9.gno:5:12 diff --git a/gnovm/tests/files/redeclaration_global0.gno b/gnovm/tests/files/redeclaration_global0.gno index 044e4d38ced..fd86fbf82f8 100644 --- a/gnovm/tests/files/redeclaration_global0.gno +++ b/gnovm/tests/files/redeclaration_global0.gno @@ -10,8 +10,8 @@ func main() { } // Error: -// files/redeclaration_global0.gno:5:5: time redeclared in this block -// previous declaration at files/redeclaration_global0.gno:3:6 +// redeclaration_global0.gno:5:5: time redeclared in this block +// previous declaration at redeclaration_global0.gno:3:6 // TypeCheckError: -// main/files/redeclaration_global0.gno:5:5: time redeclared in this block; main/files/redeclaration_global0.gno:3:6: other declaration of time; main/files/redeclaration_global0.gno:8:2: time (type) is not an expression; main/files/redeclaration_global0.gno:9:10: time (type) is not an expression +// main/redeclaration_global0.gno:5:5: time redeclared in this block; main/redeclaration_global0.gno:3:6: other declaration of time; main/redeclaration_global0.gno:8:2: time (type) is not an expression; main/redeclaration_global0.gno:9:10: time (type) is not an expression diff --git a/gnovm/tests/files/redeclaration_global1.gno b/gnovm/tests/files/redeclaration_global1.gno index 256cb0d2b7c..761e2bd605b 100644 --- a/gnovm/tests/files/redeclaration_global1.gno +++ b/gnovm/tests/files/redeclaration_global1.gno @@ -10,8 +10,8 @@ func main() { } // Error: -// files/redeclaration_global1.gno:5:6: time redeclared in this block -// previous declaration at files/redeclaration_global1.gno:3:5 +// redeclaration_global1.gno:5:6: time redeclared in this block +// previous declaration at redeclaration_global1.gno:3:5 // TypeCheckError: -// main/files/redeclaration_global1.gno:5:6: time redeclared in this block; main/files/redeclaration_global1.gno:3:5: other declaration of time; main/files/redeclaration_global1.gno:8:8: time is not a type +// main/redeclaration_global1.gno:5:6: time redeclared in this block; main/redeclaration_global1.gno:3:5: other declaration of time; main/redeclaration_global1.gno:8:8: time is not a type diff --git a/gnovm/tests/files/redeclaration_global5.gno b/gnovm/tests/files/redeclaration_global5.gno index 20e63d74f98..ba29191390e 100644 --- a/gnovm/tests/files/redeclaration_global5.gno +++ b/gnovm/tests/files/redeclaration_global5.gno @@ -12,8 +12,8 @@ func main() { } // Error: -// files/redeclaration_global5.gno:5:6: time redeclared in this block -// previous declaration at files/redeclaration_global5.gno:3:5 +// redeclaration_global5.gno:5:6: time redeclared in this block +// previous declaration at redeclaration_global5.gno:3:5 // TypeCheckError: -// main/files/redeclaration_global5.gno:5:6: time redeclared in this block; main/files/redeclaration_global5.gno:3:5: other declaration of time; main/files/redeclaration_global5.gno:10:7: invalid operation: cannot call non-function time (variable of type int) +// main/redeclaration_global5.gno:5:6: time redeclared in this block; main/redeclaration_global5.gno:3:5: other declaration of time; main/redeclaration_global5.gno:10:7: invalid operation: cannot call non-function time (variable of type int) diff --git a/gnovm/tests/files/redefine6.gno b/gnovm/tests/files/redefine6.gno index c56306bf630..669ce3eab8b 100644 --- a/gnovm/tests/files/redefine6.gno +++ b/gnovm/tests/files/redefine6.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// files/redefine6.gno:5:2: no new variables on left side of := +// redefine6.gno:5:2: no new variables on left side of := // TypeCheckError: -// main/files/redefine6.gno:5:7: no new variables on left side of :=; main/files/redefine6.gno:4:2: declared and not used: a; main/files/redefine6.gno:4:5: declared and not used: b +// main/redefine6.gno:5:7: no new variables on left side of :=; main/redefine6.gno:4:2: declared and not used: a; main/redefine6.gno:4:5: declared and not used: b diff --git a/gnovm/tests/files/slice2.gno b/gnovm/tests/files/slice2.gno index 67e51ca75d8..3fb55e3e52e 100644 --- a/gnovm/tests/files/slice2.gno +++ b/gnovm/tests/files/slice2.gno @@ -8,4 +8,4 @@ func main() { // duplicate index 2 in array or slice literal // TypeCheckError: -// main/files/slice2.gno:4:35: duplicate index 2 in array or slice literal +// main/slice2.gno:4:35: duplicate index 2 in array or slice literal diff --git a/gnovm/tests/files/slice3.gno b/gnovm/tests/files/slice3.gno index ccf2291d92a..b390d295b10 100644 --- a/gnovm/tests/files/slice3.gno +++ b/gnovm/tests/files/slice3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/slice3.gno:4:7: cannot use nil as string value in array, slice literal or map literal +// main/slice3.gno:4:7: cannot use nil as string value in array, slice literal or map literal // TypeCheckError: -// main/files/slice3.gno:4:16: cannot use nil as string value in array or slice literal +// main/slice3.gno:4:16: cannot use nil as string value in array or slice literal diff --git a/gnovm/tests/files/slice4.gno b/gnovm/tests/files/slice4.gno index 260bcee6006..90e8c33f412 100644 --- a/gnovm/tests/files/slice4.gno +++ b/gnovm/tests/files/slice4.gno @@ -9,4 +9,4 @@ func main() { // allocation limit exceeded // TypeCheckError: -// main/files/slice4.gno:5:2: declared and not used: b +// main/slice4.gno:5:2: declared and not used: b diff --git a/gnovm/tests/files/struct2b.gno b/gnovm/tests/files/struct2b.gno index 7ff345ff25e..887eed113df 100644 --- a/gnovm/tests/files/struct2b.gno +++ b/gnovm/tests/files/struct2b.gno @@ -14,4 +14,4 @@ func main() { // duplicate field name f in struct literal // TypeCheckError: -// main/files/struct2b.gno:10:26: duplicate field name f in struct literal; main/files/struct2b.gno:10:32: duplicate field name h in struct literal +// main/struct2b.gno:10:26: duplicate field name f in struct literal; main/struct2b.gno:10:32: duplicate field name h in struct literal diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files/switch13.gno index 66f90153ef3..5a34da281c1 100644 --- a/gnovm/tests/files/switch13.gno +++ b/gnovm/tests/files/switch13.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/switch13.gno:9:2: i is not a type +// main/switch13.gno:9:2: i is not a type // TypeCheckError: -// main/files/switch13.gno:9:7: i is not a type +// main/switch13.gno:9:7: i is not a type diff --git a/gnovm/tests/files/switch19.gno b/gnovm/tests/files/switch19.gno index 1c9f7faef97..92d39635e08 100644 --- a/gnovm/tests/files/switch19.gno +++ b/gnovm/tests/files/switch19.gno @@ -48,7 +48,7 @@ func main() { } // Error: -// main/files/switch19.gno:34:2: duplicate type main.Bir in type switch +// main/switch19.gno:34:2: duplicate type main.Bir in type switch // TypeCheckError: -// main/files/switch19.gno:37:7: duplicate case Bir in type switch; main/files/switch19.gno:35:12: previous case +// main/switch19.gno:37:7: duplicate case Bir in type switch; main/switch19.gno:35:12: previous case diff --git a/gnovm/tests/files/switch8.gno b/gnovm/tests/files/switch8.gno index b425fd7ee37..f300e69d211 100644 --- a/gnovm/tests/files/switch8.gno +++ b/gnovm/tests/files/switch8.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/switch8.gno:5:2: fallthrough statement out of place +// main/switch8.gno:5:2: fallthrough statement out of place // TypeCheckError: -// main/files/switch8.gno:5:2: fallthrough statement out of place +// main/switch8.gno:5:2: fallthrough statement out of place diff --git a/gnovm/tests/files/switch8b.gno b/gnovm/tests/files/switch8b.gno index a8b1e14536a..eef0e2a9268 100644 --- a/gnovm/tests/files/switch8b.gno +++ b/gnovm/tests/files/switch8b.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/switch8b.gno:10:3: cannot fallthrough final case in switch +// main/switch8b.gno:10:3: cannot fallthrough final case in switch // TypeCheckError: -// main/files/switch8b.gno:10:3: cannot fallthrough final case in switch +// main/switch8b.gno:10:3: cannot fallthrough final case in switch diff --git a/gnovm/tests/files/switch8c.gno b/gnovm/tests/files/switch8c.gno index 5f0dfee4a2c..519e5d71649 100644 --- a/gnovm/tests/files/switch8c.gno +++ b/gnovm/tests/files/switch8c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/switch8c.gno:7:3: fallthrough statement out of place +// main/switch8c.gno:7:3: fallthrough statement out of place // TypeCheckError: -// main/files/switch8c.gno:7:3: fallthrough statement out of place +// main/switch8c.gno:7:3: fallthrough statement out of place diff --git a/gnovm/tests/files/switch9.gno b/gnovm/tests/files/switch9.gno index efe5f3af22f..cfb568dd985 100644 --- a/gnovm/tests/files/switch9.gno +++ b/gnovm/tests/files/switch9.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/switch9.gno:9:3: cannot fallthrough in type switch +// main/switch9.gno:9:3: cannot fallthrough in type switch // TypeCheckError: -// main/files/switch9.gno:9:3: cannot fallthrough in type switch +// main/switch9.gno:9:3: cannot fallthrough in type switch diff --git a/gnovm/tests/files/type30.gno b/gnovm/tests/files/type30.gno index b093d1eb526..a71520f953b 100644 --- a/gnovm/tests/files/type30.gno +++ b/gnovm/tests/files/type30.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/type30.gno:15:10: cannot use main.String as string without explicit conversion +// main/type30.gno:15:10: cannot use main.String as string without explicit conversion // TypeCheckError: -// main/files/type30.gno:15:19: cannot use y (variable of string type String) as string value in argument to equal +// main/type30.gno:15:19: cannot use y (variable of string type String) as string value in argument to equal diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index 092cf358969..1d8173615d9 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/type31.gno:8:10: invalid operation: mismatched types string and main.String +// main/type31.gno:8:10: invalid operation: mismatched types string and main.String // TypeCheckError: -// main/files/type31.gno:8:10: invalid operation: x + y (mismatched types string and String) +// main/type31.gno:8:10: invalid operation: x + y (mismatched types string and String) diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index f94f8211268..caa6ed31c5f 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/type32.gno:9:11: invalid operation: mismatched types string and main.S +// main/type32.gno:9:11: invalid operation: mismatched types string and main.S // TypeCheckError: -// main/files/type32.gno:9:11: invalid operation: a + ":" + b (mismatched types string and S) +// main/type32.gno:9:11: invalid operation: a + ":" + b (mismatched types string and S) diff --git a/gnovm/tests/files/type37.gno b/gnovm/tests/files/type37.gno index 880ef0748b8..de6c2f60f36 100644 --- a/gnovm/tests/files/type37.gno +++ b/gnovm/tests/files/type37.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/type37.gno:8:1: invalid receiver type main.Arr (base type is pointer type) +// main/type37.gno:8:1: invalid receiver type main.Arr (base type is pointer type) // TypeCheckError: -// main/files/type37.gno:8:9: invalid receiver type Arr (pointer or interface type); main/files/type37.gno:14:9: Arr(a).Add undefined (type Arr has no field or method Add) +// main/type37.gno:8:9: invalid receiver type Arr (pointer or interface type); main/type37.gno:14:9: Arr(a).Add undefined (type Arr has no field or method Add) diff --git a/gnovm/tests/files/type37b.gno b/gnovm/tests/files/type37b.gno index a6c84955d94..17211a96352 100644 --- a/gnovm/tests/files/type37b.gno +++ b/gnovm/tests/files/type37b.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/type37b.gno:7:1: invalid receiver type **main.Integer (base type is pointer type) +// main/type37b.gno:7:1: invalid receiver type **main.Integer (base type is pointer type) // TypeCheckError: -// main/files/type37b.gno:7:10: invalid receiver type **Integer; main/files/type37b.gno:16:4: b.Add undefined (type **Integer has no field or method Add) +// main/type37b.gno:7:10: invalid receiver type **Integer; main/type37b.gno:16:4: b.Add undefined (type **Integer has no field or method Add) diff --git a/gnovm/tests/files/type37d.gno b/gnovm/tests/files/type37d.gno index ba0cbcb8108..3650cdc8c4e 100644 --- a/gnovm/tests/files/type37d.gno +++ b/gnovm/tests/files/type37d.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/type37d.gno:7:1: invalid receiver type main.IntPtr (base type is pointer type) +// main/type37d.gno:7:1: invalid receiver type main.IntPtr (base type is pointer type) // TypeCheckError: -// main/files/type37d.gno:7:9: invalid receiver type IntPtr (pointer or interface type); main/files/type37d.gno:12:13: ip.Int undefined (type IntPtr has no field or method Int) +// main/type37d.gno:7:9: invalid receiver type IntPtr (pointer or interface type); main/type37d.gno:12:13: ip.Int undefined (type IntPtr has no field or method Int) diff --git a/gnovm/tests/files/type37e.gno b/gnovm/tests/files/type37e.gno index c897a734c1a..239202ac92d 100644 --- a/gnovm/tests/files/type37e.gno +++ b/gnovm/tests/files/type37e.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/type37e.gno:8:1: invalid receiver type main.Int2 (base type is pointer type) +// main/type37e.gno:8:1: invalid receiver type main.Int2 (base type is pointer type) // TypeCheckError: -// main/files/type37e.gno:8:10: invalid receiver type Int2 (pointer or interface type); main/files/type37e.gno:13:19: Int2(ip).Int undefined (type Int2 has no field or method Int) +// main/type37e.gno:8:10: invalid receiver type Int2 (pointer or interface type); main/type37e.gno:13:19: Int2(ip).Int undefined (type Int2 has no field or method Int) diff --git a/gnovm/tests/files/type37f.gno b/gnovm/tests/files/type37f.gno index 074f79bbf34..3d4e1047eef 100644 --- a/gnovm/tests/files/type37f.gno +++ b/gnovm/tests/files/type37f.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/type37f.gno:7:1: invalid receiver type *main.IntPtr (base type is pointer type) +// main/type37f.gno:7:1: invalid receiver type *main.IntPtr (base type is pointer type) // TypeCheckError: -// main/files/type37f.gno:7:10: invalid receiver type IntPtr (pointer or interface type) +// main/type37f.gno:7:10: invalid receiver type IntPtr (pointer or interface type) diff --git a/gnovm/tests/files/type39.gno b/gnovm/tests/files/type39.gno index 2b1f6b278a2..565052a8a3f 100644 --- a/gnovm/tests/files/type39.gno +++ b/gnovm/tests/files/type39.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/type39.gno:7:1: invalid receiver type main.foo (base type is interface type) +// main/type39.gno:7:1: invalid receiver type main.foo (base type is interface type) // TypeCheckError: -// main/files/type39.gno:7:9: invalid receiver type foo (pointer or interface type) +// main/type39.gno:7:9: invalid receiver type foo (pointer or interface type) diff --git a/gnovm/tests/files/type39a.gno b/gnovm/tests/files/type39a.gno index 4204d1ff081..7b31616ac16 100644 --- a/gnovm/tests/files/type39a.gno +++ b/gnovm/tests/files/type39a.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/files/type39a.gno:9:1: invalid receiver type main.FF (base type is interface type) +// main/type39a.gno:9:1: invalid receiver type main.FF (base type is interface type) // TypeCheckError: -// main/files/type39a.gno:9:9: invalid receiver type FF (pointer or interface type); main/files/type39a.gno:20:12: f.echo undefined (type foo has no field or method echo) +// main/type39a.gno:9:9: invalid receiver type FF (pointer or interface type); main/type39a.gno:20:12: f.echo undefined (type foo has no field or method echo) diff --git a/gnovm/tests/files/type39b.gno b/gnovm/tests/files/type39b.gno index 8c89273296c..e45bee03871 100644 --- a/gnovm/tests/files/type39b.gno +++ b/gnovm/tests/files/type39b.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/type39b.gno:7:1: invalid receiver type *main.foo (base type is interface type) +// main/type39b.gno:7:1: invalid receiver type *main.foo (base type is interface type) // TypeCheckError: -// main/files/type39b.gno:7:10: invalid receiver type foo (pointer or interface type); main/files/type39b.gno:18:12: f.echo undefined (type *foo is pointer to interface, not interface) +// main/type39b.gno:7:10: invalid receiver type foo (pointer or interface type); main/type39b.gno:18:12: f.echo undefined (type *foo is pointer to interface, not interface) diff --git a/gnovm/tests/files/type41.gno b/gnovm/tests/files/type41.gno index a9b0a171350..448c67ac60a 100644 --- a/gnovm/tests/files/type41.gno +++ b/gnovm/tests/files/type41.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/type41.gno:3:6: nil is not a type +// main/type41.gno:3:6: nil is not a type // TypeCheckError: -// main/files/type41.gno:3:8: nil is not a type +// main/type41.gno:3:8: nil is not a type diff --git a/gnovm/tests/files/type42.gno b/gnovm/tests/files/type42.gno index f7ee84682d0..f04b10a1634 100644 --- a/gnovm/tests/files/type42.gno +++ b/gnovm/tests/files/type42.gno @@ -10,7 +10,7 @@ func main() { // Output: // (1 main.A) -// ("a" main[main/files/type42.gno:5:1].A) +// ("a" main[main/type42.gno:5:1-9:2].A) // Preprocessed: -// file{ package main; type A (const-type main.A); func main() { (const (println func(...interface {})))((const (1 main.A))); type A (const-type main[main/files/type42.gno:5:1].A); (const (println func(...interface {})))((const ("a" main[main/files/type42.gno:5:1].A))) } } +// file{ package main; type A (const-type main.A); func main() { (const (println func(...interface {})))((const (1 main.A))); type A (const-type main[main/type42.gno:5:1-9:2].A); (const (println func(...interface {})))((const ("a" main[main/type42.gno:5:1-9:2].A))) } } diff --git a/gnovm/tests/files/typeassert1.gno b/gnovm/tests/files/typeassert1.gno index f6609a3d18c..b1d449450d7 100644 --- a/gnovm/tests/files/typeassert1.gno +++ b/gnovm/tests/files/typeassert1.gno @@ -12,7 +12,7 @@ func main() { // Stacktrace: // panic: interface conversion: interface is nil, not main.A // main() -// main/files/typeassert1.gno:9 +// main/typeassert1.gno:9 // Error: // interface conversion: interface is nil, not main.A diff --git a/gnovm/tests/files/typeassert2a.gno b/gnovm/tests/files/typeassert2a.gno index 2ce01bbf28c..5edf1ea07c8 100644 --- a/gnovm/tests/files/typeassert2a.gno +++ b/gnovm/tests/files/typeassert2a.gno @@ -14,9 +14,9 @@ func main() { // Stacktrace: // panic: interface conversion: interface is nil, not main.A // defer func(){ ... }() -// main/files/typeassert2a.gno:10 +// main/typeassert2a.gno:10 // main() -// main/files/typeassert2a.gno:8 +// main/typeassert2a.gno:8 // Error: // interface conversion: interface is nil, not main.A diff --git a/gnovm/tests/files/typeassert3.gno b/gnovm/tests/files/typeassert3.gno index 49ed48e26e6..6e6c5d8a189 100644 --- a/gnovm/tests/files/typeassert3.gno +++ b/gnovm/tests/files/typeassert3.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/typeassert3.gno:9:8: cannot use _ as value or type +// main/typeassert3.gno:9:8: cannot use _ as value or type // TypeCheckError: -// main/files/typeassert3.gno:9:8: cannot use _ as value or type +// main/typeassert3.gno:9:8: cannot use _ as value or type diff --git a/gnovm/tests/files/typeassert8.gno b/gnovm/tests/files/typeassert8.gno index 2115ce51303..f0b2460ea4e 100644 --- a/gnovm/tests/files/typeassert8.gno +++ b/gnovm/tests/files/typeassert8.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/files/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface // TypeCheckError: -// main/files/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface diff --git a/gnovm/tests/files/typeassert8a.gno b/gnovm/tests/files/typeassert8a.gno index 9c5a59e3f87..19d11578852 100644 --- a/gnovm/tests/files/typeassert8a.gno +++ b/gnovm/tests/files/typeassert8a.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/files/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface // TypeCheckError: -// main/files/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface diff --git a/gnovm/tests/files/typeassert9.gno b/gnovm/tests/files/typeassert9.gno index 6ea072661c1..ca9b8a28170 100644 --- a/gnovm/tests/files/typeassert9.gno +++ b/gnovm/tests/files/typeassert9.gno @@ -19,7 +19,7 @@ func main() { // Stacktrace: // panic: interface conversion: interface is nil, not main.Writer // main() -// main/files/typeassert9.gno:16 +// main/typeassert9.gno:16 // Error: // interface conversion: interface is nil, not main.Writer diff --git a/gnovm/tests/files/typeassert9a.gno b/gnovm/tests/files/typeassert9a.gno index 113137f0e3b..21481f72d81 100644 --- a/gnovm/tests/files/typeassert9a.gno +++ b/gnovm/tests/files/typeassert9a.gno @@ -16,9 +16,9 @@ func main() { } // Error: -// main/files/typeassert9a.gno:15:6: *main.csvReader does not implement main.Reader (wrong type for method Read) +// main/typeassert9a.gno:15:6: *main.csvReader does not implement main.Reader (wrong type for method Read) // TypeCheckError: -// main/files/typeassert9a.gno:15:25: cannot use &csvReader{} (value of type *csvReader) as Reader value in variable declaration: *csvReader does not implement Reader (wrong type for method Read) +// main/typeassert9a.gno:15:25: cannot use &csvReader{} (value of type *csvReader) as Reader value in variable declaration: *csvReader does not implement Reader (wrong type for method Read) // have Read(string) string -// want Read(int) string; main/files/typeassert9a.gno:15:6: declared and not used: csvReader +// want Read(int) string; main/typeassert9a.gno:15:6: declared and not used: csvReader diff --git a/gnovm/tests/files/types/add_a0.gno b/gnovm/tests/files/types/add_a0.gno index 11155847c44..1796575aeb0 100644 --- a/gnovm/tests/files/types/add_a0.gno +++ b/gnovm/tests/files/types/add_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/add_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/add_a0.gno:5:10: invalid operation: mismatched types int and int8 // TypeCheckError: -// main/files/types/add_a0.gno:5:10: invalid operation: int(1) + int8(1) (mismatched types int and int8) +// main/add_a0.gno:5:10: invalid operation: int(1) + int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/add_a1.gno b/gnovm/tests/files/types/add_a1.gno index 02f097ebc25..f54131dc367 100644 --- a/gnovm/tests/files/types/add_a1.gno +++ b/gnovm/tests/files/types/add_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/add_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/add_a1.gno:21:10: invalid operation: Error1(0) + Error2(0) (mismatched types Error1 and Error2) +// main/add_a1.gno:21:10: invalid operation: Error1(0) + Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_a0.gno b/gnovm/tests/files/types/add_assign_a0.gno index 8553e8bdf26..339229efbe6 100644 --- a/gnovm/tests/files/types/add_assign_a0.gno +++ b/gnovm/tests/files/types/add_assign_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/add_assign_a0.gno:5:2: invalid operation: mismatched types int and int8 +// main/add_assign_a0.gno:5:2: invalid operation: mismatched types int and int8 // TypeCheckError: -// main/files/types/add_assign_a0.gno:5:2: invalid operation: int(0) += int8(1) (mismatched types int and int8) +// main/add_assign_a0.gno:5:2: invalid operation: int(0) += int8(1) (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 index f6f85092ce4..135135c6ee7 100644 --- a/gnovm/tests/files/types/add_assign_a1.gno +++ b/gnovm/tests/files/types/add_assign_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/add_assign_a1.gno:21:2: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_assign_a1.gno:21:2: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/add_assign_a1.gno:21:2: invalid operation: Error1(0) += Error2(0) (mismatched types Error1 and Error2) +// main/add_assign_a1.gno:21:2: invalid operation: Error1(0) += Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_a_01.gno b/gnovm/tests/files/types/add_assign_a_01.gno index 494df4f84d9..9963a0a7504 100644 --- a/gnovm/tests/files/types/add_assign_a_01.gno +++ b/gnovm/tests/files/types/add_assign_a_01.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/add_assign_a_01.gno:6:2: assignment operator += requires only one expression on lhs and rhs +// main/add_assign_a_01.gno:6:2: assignment operator += requires only one expression on lhs and rhs // TypeCheckError: -// main/files/types/add_assign_a_01.gno:6:7: assignment operation += requires single-valued expressions +// main/add_assign_a_01.gno:6:7: assignment operation += requires single-valued expressions diff --git a/gnovm/tests/files/types/add_assign_b0.gno b/gnovm/tests/files/types/add_assign_b0.gno index 94e00216c0c..6a030aec1ad 100644 --- a/gnovm/tests/files/types/add_assign_b0.gno +++ b/gnovm/tests/files/types/add_assign_b0.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/add_assign_b0.gno:8:2: invalid operation: mismatched types int and main.Error +// main/add_assign_b0.gno:8:2: invalid operation: mismatched types int and main.Error // TypeCheckError: -// main/files/types/add_assign_b0.gno:8:2: invalid operation: r += Error(1) (mismatched types int and Error) +// main/add_assign_b0.gno:8:2: invalid operation: r += Error(1) (mismatched types int and Error) diff --git a/gnovm/tests/files/types/add_assign_e0.gno b/gnovm/tests/files/types/add_assign_e0.gno index 4a835da40f1..38e41c8e9cc 100644 --- a/gnovm/tests/files/types/add_assign_e0.gno +++ b/gnovm/tests/files/types/add_assign_e0.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/add_assign_e0.gno:23:2: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_assign_e0.gno:23:2: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/add_assign_e0.gno:23:2: invalid operation: e1 += e2 (mismatched types Error1 and Error2) +// main/add_assign_e0.gno:23:2: invalid operation: e1 += e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_f0.gno b/gnovm/tests/files/types/add_assign_f0.gno index 9159a90ff14..3c1d62941df 100644 --- a/gnovm/tests/files/types/add_assign_f0.gno +++ b/gnovm/tests/files/types/add_assign_f0.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/add_assign_f0.gno:20:2: invalid operation: mismatched types int and .uverse.error +// main/add_assign_f0.gno:20:2: invalid operation: mismatched types int and .uverse.error // TypeCheckError: -// main/files/types/add_assign_f0.gno:20:2: invalid operation: r += errCmp (mismatched types int and error) +// main/add_assign_f0.gno:20:2: invalid operation: r += errCmp (mismatched types int and error) diff --git a/gnovm/tests/files/types/add_assign_f1.gno b/gnovm/tests/files/types/add_assign_f1.gno index 8552426c881..707fe95c465 100644 --- a/gnovm/tests/files/types/add_assign_f1.gno +++ b/gnovm/tests/files/types/add_assign_f1.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/add_assign_f1.gno:21:2: invalid operation: mismatched types main.Error and .uverse.error +// main/add_assign_f1.gno:21:2: invalid operation: mismatched types main.Error and .uverse.error // TypeCheckError: -// main/files/types/add_assign_f1.gno:21:2: invalid operation: r += errCmp (mismatched types Error and error) +// main/add_assign_f1.gno:21:2: invalid operation: r += errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/add_assign_f2.gno b/gnovm/tests/files/types/add_assign_f2.gno index e9abf4b6669..7f891492bbd 100644 --- a/gnovm/tests/files/types/add_assign_f2.gno +++ b/gnovm/tests/files/types/add_assign_f2.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/add_assign_f2.gno:20:2: operator += not defined on: InterfaceKind +// main/add_assign_f2.gno:20:2: operator += not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_assign_f2.gno:20:2: invalid operation: errCmp += r (mismatched types error and Error) +// main/add_assign_f2.gno:20:2: invalid operation: errCmp += r (mismatched types error and Error) diff --git a/gnovm/tests/files/types/add_assign_f3.gno b/gnovm/tests/files/types/add_assign_f3.gno index d0befd8fdb1..87835bcf390 100644 --- a/gnovm/tests/files/types/add_assign_f3.gno +++ b/gnovm/tests/files/types/add_assign_f3.gno @@ -29,7 +29,7 @@ func main() { } // Error: -// main/files/types/add_assign_f3.gno:27:2: operator += not defined on: InterfaceKind +// main/add_assign_f3.gno:27:2: operator += not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_assign_f3.gno:27:2: invalid operation: operator + not defined on e1 (variable of interface type E) +// main/add_assign_f3.gno:27:2: invalid operation: operator + not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/add_b2.gno b/gnovm/tests/files/types/add_b2.gno index 5ab40776aa3..6ba2bd821cf 100644 --- a/gnovm/tests/files/types/add_b2.gno +++ b/gnovm/tests/files/types/add_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/add_b2.gno:5:10: cannot use untyped Bigint as StringKind +// main/add_b2.gno:5:10: cannot use untyped Bigint as StringKind // TypeCheckError: -// main/files/types/add_b2.gno:5:10: invalid operation: 1 + "a" (mismatched types untyped int and untyped string) +// main/add_b2.gno:5:10: invalid operation: 1 + "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/add_d4.gno b/gnovm/tests/files/types/add_d4.gno index 1c7655bc320..dd2c97d4a9c 100644 --- a/gnovm/tests/files/types/add_d4.gno +++ b/gnovm/tests/files/types/add_d4.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/add_d4.gno:7:10: operator + not defined on: InterfaceKind +// main/add_d4.gno:7:10: operator + not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_d4.gno:7:10: invalid operation: b + a (mismatched types any and int) +// main/add_d4.gno:7:10: invalid operation: b + a (mismatched types any and int) diff --git a/gnovm/tests/files/types/add_e0.gno b/gnovm/tests/files/types/add_e0.gno index d1b2f73acf9..8e05aff56a3 100644 --- a/gnovm/tests/files/types/add_e0.gno +++ b/gnovm/tests/files/types/add_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/add_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types Error1 and Error2) +// main/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_f0.gno b/gnovm/tests/files/types/add_f0.gno index e7fa6844fe0..853a5fe3848 100644 --- a/gnovm/tests/files/types/add_f0.gno +++ b/gnovm/tests/files/types/add_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/add_f0.gno:19:10: operator + not defined on: InterfaceKind +// main/add_f0.gno:19:10: operator + not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} +// main/add_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/add_f1.gno b/gnovm/tests/files/types/add_f1.gno index 5a2209fff24..0d68ecbb213 100644 --- a/gnovm/tests/files/types/add_f1.gno +++ b/gnovm/tests/files/types/add_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/add_f1.gno:19:10: operator + not defined on: InterfaceKind +// main/add_f1.gno:19:10: operator + not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_f1.gno:19:10: invalid operation: Error(0) + errCmp (mismatched types Error and error) +// main/add_f1.gno:19:10: invalid operation: Error(0) + errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/add_f2.gno b/gnovm/tests/files/types/add_f2.gno index 5a54dc42ecc..1da2b73ab49 100644 --- a/gnovm/tests/files/types/add_f2.gno +++ b/gnovm/tests/files/types/add_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/files/types/add_f2.gno:27:10: operator + not defined on: InterfaceKind +// main/add_f2.gno:27:10: operator + not defined on: InterfaceKind // TypeCheckError: -// main/files/types/add_f2.gno:27:10: invalid operation: operator + not defined on e1 (variable of interface type E) +// main/add_f2.gno:27:10: invalid operation: operator + not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/and_a0.gno b/gnovm/tests/files/types/and_a0.gno index cd8e6e3b49c..cd595f11c20 100644 --- a/gnovm/tests/files/types/and_a0.gno +++ b/gnovm/tests/files/types/and_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/and_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/and_a0.gno:5:10: invalid operation: mismatched types int and int8 // TypeCheckError: -// main/files/types/and_a0.gno:5:10: invalid operation: int(0) & int8(1) (mismatched types int and int8) +// main/and_a0.gno:5:10: invalid operation: int(0) & int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/and_a1.gno b/gnovm/tests/files/types/and_a1.gno index 2e5df8f5279..84ad0de1692 100644 --- a/gnovm/tests/files/types/and_a1.gno +++ b/gnovm/tests/files/types/and_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/and_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/and_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/and_a1.gno:21:10: invalid operation: Error1(0) & Error2(0) (mismatched types Error1 and Error2) +// main/and_a1.gno:21:10: invalid operation: Error1(0) & Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_b2.gno b/gnovm/tests/files/types/and_b2.gno index b504ecdc50f..229555bfc87 100644 --- a/gnovm/tests/files/types/and_b2.gno +++ b/gnovm/tests/files/types/and_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/and_b2.gno:5:10: operator & not defined on: StringKind +// main/and_b2.gno:5:10: operator & not defined on: StringKind // TypeCheckError: -// main/files/types/and_b2.gno:5:10: invalid operation: 1 & "a" (mismatched types untyped int and untyped string) +// main/and_b2.gno:5:10: invalid operation: 1 & "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/and_b3.gno b/gnovm/tests/files/types/and_b3.gno index 3f2c4ed6179..8de2636ab85 100644 --- a/gnovm/tests/files/types/and_b3.gno +++ b/gnovm/tests/files/types/and_b3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/and_b3.gno:5:10: operator & not defined on: StringKind +// main/and_b3.gno:5:10: operator & not defined on: StringKind // TypeCheckError: -// main/files/types/and_b3.gno:5:10: invalid operation: operator & not defined on "b" (untyped string constant) +// main/and_b3.gno:5:10: invalid operation: operator & not defined on "b" (untyped string constant) diff --git a/gnovm/tests/files/types/and_d0.gno b/gnovm/tests/files/types/and_d0.gno index 5ed24e07460..fc240a1e7c0 100644 --- a/gnovm/tests/files/types/and_d0.gno +++ b/gnovm/tests/files/types/and_d0.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/and_d0.gno:6:10: operator & not defined on: BigdecKind +// main/and_d0.gno:6:10: operator & not defined on: BigdecKind // TypeCheckError: -// main/files/types/and_d0.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) +// main/and_d0.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/and_d4.gno b/gnovm/tests/files/types/and_d4.gno index b3c441ca088..898a5065eb9 100644 --- a/gnovm/tests/files/types/and_d4.gno +++ b/gnovm/tests/files/types/and_d4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/and_d4.gno:6:10: operator & not defined on: BigdecKind +// main/and_d4.gno:6:10: operator & not defined on: BigdecKind // TypeCheckError: -// main/files/types/and_d4.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) +// main/and_d4.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/and_e0.gno b/gnovm/tests/files/types/and_e0.gno index d6fd41ed2e1..8129563ac16 100644 --- a/gnovm/tests/files/types/and_e0.gno +++ b/gnovm/tests/files/types/and_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/and_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/and_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types Error1 and Error2) +// main/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_f0.gno b/gnovm/tests/files/types/and_f0.gno index 0f3c7e9ff13..7cd46aedf76 100644 --- a/gnovm/tests/files/types/and_f0.gno +++ b/gnovm/tests/files/types/and_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/and_f0.gno:19:10: operator & not defined on: InterfaceKind +// main/and_f0.gno:19:10: operator & not defined on: InterfaceKind // TypeCheckError: -// main/files/types/and_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} +// main/and_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/and_f1.gno b/gnovm/tests/files/types/and_f1.gno index 3d7848a2d84..6902301dde2 100644 --- a/gnovm/tests/files/types/and_f1.gno +++ b/gnovm/tests/files/types/and_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/and_f1.gno:19:10: operator & not defined on: InterfaceKind +// main/and_f1.gno:19:10: operator & not defined on: InterfaceKind // TypeCheckError: -// main/files/types/and_f1.gno:19:10: invalid operation: Error(0) & errCmp (mismatched types Error and error) +// main/and_f1.gno:19:10: invalid operation: Error(0) & errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/and_f2.gno b/gnovm/tests/files/types/and_f2.gno index b1338442aca..f8ef2526d39 100644 --- a/gnovm/tests/files/types/and_f2.gno +++ b/gnovm/tests/files/types/and_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/files/types/and_f2.gno:27:10: operator & not defined on: InterfaceKind +// main/and_f2.gno:27:10: operator & not defined on: InterfaceKind // TypeCheckError: -// main/files/types/and_f2.gno:27:10: invalid operation: operator & not defined on e1 (variable of interface type E) +// main/and_f2.gno:27:10: invalid operation: operator & not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/assign_call.gno b/gnovm/tests/files/types/assign_call.gno index 1fc0b898738..260c25c866f 100644 --- a/gnovm/tests/files/types/assign_call.gno +++ b/gnovm/tests/files/types/assign_call.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/assign_call.gno:9:2: cannot use int as string +// main/assign_call.gno:9:2: cannot use int as string // TypeCheckError: -// main/files/types/assign_call.gno:9:10: cannot use foo() (value of type int) as string value in assignment; main/files/types/assign_call.gno:9:10: cannot use foo() (value of type float32) as string value in assignment; main/files/types/assign_call.gno:8:9: declared and not used: s1 +// main/assign_call.gno:9:10: cannot use foo() (value of type int) as string value in assignment; main/assign_call.gno:9:10: cannot use foo() (value of type float32) as string value in assignment; main/assign_call.gno:8:9: declared and not used: s1 diff --git a/gnovm/tests/files/types/assign_index.gno b/gnovm/tests/files/types/assign_index.gno index cdb10cb6b57..77e2364967f 100644 --- a/gnovm/tests/files/types/assign_index.gno +++ b/gnovm/tests/files/types/assign_index.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/assign_index.gno:8:2: cannot use int as string +// main/assign_index.gno:8:2: cannot use int as string // TypeCheckError: -// main/files/types/assign_index.gno:8:10: cannot use m["a"] (map index expression of type int) as string value in assignment +// main/assign_index.gno:8:10: cannot use m["a"] (map index expression of type int) as string value in assignment diff --git a/gnovm/tests/files/types/assign_index_a.gno b/gnovm/tests/files/types/assign_index_a.gno index 32f16888223..3ca128b2a83 100644 --- a/gnovm/tests/files/types/assign_index_a.gno +++ b/gnovm/tests/files/types/assign_index_a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/assign_index_a.gno:6:2: cannot use int as string +// main/assign_index_a.gno:6:2: cannot use int as string // TypeCheckError: -// main/files/types/assign_index_a.gno:6:10: cannot use map[string]int{…}["a"] (map index expression of type int) as string value in assignment +// main/assign_index_a.gno:6:10: cannot use map[string]int{…}["a"] (map index expression of type int) as string value in assignment diff --git a/gnovm/tests/files/types/assign_index_b.gno b/gnovm/tests/files/types/assign_index_b.gno index ac7559e8f75..3c6f68d6c65 100644 --- a/gnovm/tests/files/types/assign_index_b.gno +++ b/gnovm/tests/files/types/assign_index_b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/assign_index_b.gno:8:2: want bool type got int +// main/assign_index_b.gno:8:2: want bool type got int // TypeCheckError: -// main/files/types/assign_index_b.gno:8:10: cannot use m["a"] (untyped bool value) as int value in assignment +// main/assign_index_b.gno:8:10: cannot use m["a"] (untyped bool value) as int value in assignment diff --git a/gnovm/tests/files/types/assign_index_c.gno b/gnovm/tests/files/types/assign_index_c.gno index e3121aa4c35..f8063656b1c 100644 --- a/gnovm/tests/files/types/assign_index_c.gno +++ b/gnovm/tests/files/types/assign_index_c.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/assign_index_c.gno:7:2: cannot use int as string +// main/assign_index_c.gno:7:2: cannot use int as string // TypeCheckError: -// main/files/types/assign_index_c.gno:7:7: cannot use s[0] (variable of type int) as string value in assignment; main/files/types/assign_index_c.gno:6:6: declared and not used: s1 +// main/assign_index_c.gno:7:7: cannot use s[0] (variable of type int) as string value in assignment; main/assign_index_c.gno:6:6: declared and not used: s1 diff --git a/gnovm/tests/files/types/assign_literal.gno b/gnovm/tests/files/types/assign_literal.gno index 85054756c6b..6c77398885f 100644 --- a/gnovm/tests/files/types/assign_literal.gno +++ b/gnovm/tests/files/types/assign_literal.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/assign_literal.gno:4:2: cannot assign to (const (1 bigint)) +// main/assign_literal.gno:4:2: cannot assign to (const (1 bigint)) // TypeCheckError: -// main/files/types/assign_literal.gno:4:2: cannot assign to 1 (neither addressable nor a map index expression) +// main/assign_literal.gno:4:2: cannot assign to 1 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal10a.gno b/gnovm/tests/files/types/assign_literal10a.gno index faf5c3ff3a7..0dcad609edd 100644 --- a/gnovm/tests/files/types/assign_literal10a.gno +++ b/gnovm/tests/files/types/assign_literal10a.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/assign_literal10a.gno:13:2: cannot assign to s.add() +// main/assign_literal10a.gno:13:2: cannot assign to s.add() // TypeCheckError: -// main/files/types/assign_literal10a.gno:13:2: cannot assign to s.add() (neither addressable nor a map index expression) +// main/assign_literal10a.gno:13:2: cannot assign to s.add() (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal11.gno b/gnovm/tests/files/types/assign_literal11.gno index 276de23cec2..4f107c61a5c 100644 --- a/gnovm/tests/files/types/assign_literal11.gno +++ b/gnovm/tests/files/types/assign_literal11.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/assign_literal11.gno:6:2: cannot assign to const Pi +// main/assign_literal11.gno:6:2: cannot assign to const Pi // TypeCheckError: -// main/files/types/assign_literal11.gno:6:2: cannot assign to Pi (neither addressable nor a map index expression) +// main/assign_literal11.gno:6:2: cannot assign to Pi (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal2.gno b/gnovm/tests/files/types/assign_literal2.gno index 5ce3ef23e06..318fee0f1ed 100644 --- a/gnovm/tests/files/types/assign_literal2.gno +++ b/gnovm/tests/files/types/assign_literal2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/assign_literal2.gno:5:2: cannot assign to (const (2 bigint)) +// main/assign_literal2.gno:5:2: cannot assign to (const (2 bigint)) // TypeCheckError: -// main/files/types/assign_literal2.gno:5:5: cannot assign to 2 (neither addressable nor a map index expression); main/files/types/assign_literal2.gno:4:6: declared and not used: a +// main/assign_literal2.gno:5:5: cannot assign to 2 (neither addressable nor a map index expression); main/assign_literal2.gno:4:6: declared and not used: a diff --git a/gnovm/tests/files/types/assign_literal2_a.gno b/gnovm/tests/files/types/assign_literal2_a.gno index 08414393bcf..6f4ac746c07 100644 --- a/gnovm/tests/files/types/assign_literal2_a.gno +++ b/gnovm/tests/files/types/assign_literal2_a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// files/types/assign_literal2_a.gno:5:2: no new variables on left side of := +// assign_literal2_a.gno:5:2: no new variables on left side of := // TypeCheckError: -// main/files/types/assign_literal2_a.gno:5:5: non-name 2 on left side of :=; main/files/types/assign_literal2_a.gno:4:6: declared and not used: a +// main/assign_literal2_a.gno:5:5: non-name 2 on left side of :=; main/assign_literal2_a.gno:4:6: declared and not used: a diff --git a/gnovm/tests/files/types/assign_literal3.gno b/gnovm/tests/files/types/assign_literal3.gno index 06f93e7362e..1b21d220c51 100644 --- a/gnovm/tests/files/types/assign_literal3.gno +++ b/gnovm/tests/files/types/assign_literal3.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/assign_literal3.gno:4:2: cannot assign to uverse true +// main/assign_literal3.gno:4:2: cannot assign to uverse true // TypeCheckError: -// main/files/types/assign_literal3.gno:4:2: cannot assign to true (neither addressable nor a map index expression) +// main/assign_literal3.gno:4:2: cannot assign to true (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal4.gno b/gnovm/tests/files/types/assign_literal4.gno index 8d3b9603e62..73cfb0f77d8 100644 --- a/gnovm/tests/files/types/assign_literal4.gno +++ b/gnovm/tests/files/types/assign_literal4.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/assign_literal4.gno:4:2: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} +// main/assign_literal4.gno:4:2: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} // TypeCheckError: -// main/files/types/assign_literal4.gno:4:2: cannot assign to []int{…} (neither addressable nor a map index expression) +// main/assign_literal4.gno:4:2: cannot assign to []int{…} (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal4_a.gno b/gnovm/tests/files/types/assign_literal4_a.gno index 7ebba532a87..ca6429b0da9 100644 --- a/gnovm/tests/files/types/assign_literal4_a.gno +++ b/gnovm/tests/files/types/assign_literal4_a.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// files/types/assign_literal4_a.gno:4:2: no new variables on left side of := +// assign_literal4_a.gno:4:2: no new variables on left side of := // TypeCheckError: -// main/files/types/assign_literal4_a.gno:4:2: non-name []int{…} on left side of := +// main/assign_literal4_a.gno:4:2: non-name []int{…} on left side of := diff --git a/gnovm/tests/files/types/assign_literal5.gno b/gnovm/tests/files/types/assign_literal5.gno index 5de76b70139..a088ebef7f2 100644 --- a/gnovm/tests/files/types/assign_literal5.gno +++ b/gnovm/tests/files/types/assign_literal5.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/assign_literal5.gno:4:2: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} +// main/assign_literal5.gno:4:2: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} // TypeCheckError: -// main/files/types/assign_literal5.gno:4:2: cannot assign to map[string]int{…} (neither addressable nor a map index expression) +// main/assign_literal5.gno:4:2: cannot assign to map[string]int{…} (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal6.gno b/gnovm/tests/files/types/assign_literal6.gno index 46763d5769d..d37d0b07465 100644 --- a/gnovm/tests/files/types/assign_literal6.gno +++ b/gnovm/tests/files/types/assign_literal6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/assign_literal6.gno:4:2: cannot assign to (const (3 bigint)) +// main/assign_literal6.gno:4:2: cannot assign to (const (3 bigint)) // TypeCheckError: -// main/files/types/assign_literal6.gno:4:2: cannot assign to 1 + 2 (neither addressable nor a map index expression) +// main/assign_literal6.gno:4:2: cannot assign to 1 + 2 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal7c.gno b/gnovm/tests/files/types/assign_literal7c.gno index 161e3fc34d7..935869623ba 100644 --- a/gnovm/tests/files/types/assign_literal7c.gno +++ b/gnovm/tests/files/types/assign_literal7c.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/assign_literal7c.gno:7:2: cannot assign to str[(const (0 int))] +// main/assign_literal7c.gno:7:2: cannot assign to str[(const (0 int))] // TypeCheckError: -// main/files/types/assign_literal7c.gno:7:2: cannot assign to str[0] (neither addressable nor a map index expression) +// main/assign_literal7c.gno:7:2: cannot assign to str[0] (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal_a.gno b/gnovm/tests/files/types/assign_literal_a.gno index e7c01f51536..4a1e1173725 100644 --- a/gnovm/tests/files/types/assign_literal_a.gno +++ b/gnovm/tests/files/types/assign_literal_a.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// files/types/assign_literal_a.gno:4:2: no new variables on left side of := +// assign_literal_a.gno:4:2: no new variables on left side of := // TypeCheckError: -// main/files/types/assign_literal_a.gno:4:2: non-name 1 on left side of := +// main/assign_literal_a.gno:4:2: non-name 1 on left side of := diff --git a/gnovm/tests/files/types/assign_nil.gno b/gnovm/tests/files/types/assign_nil.gno index 51981cc4427..1c15fb0722b 100644 --- a/gnovm/tests/files/types/assign_nil.gno +++ b/gnovm/tests/files/types/assign_nil.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/assign_nil.gno:7:2: cannot assign to uverse nil +// main/assign_nil.gno:7:2: cannot assign to uverse nil // TypeCheckError: -// main/files/types/assign_nil.gno:7:5: cannot assign to nil (neither addressable nor a map index expression); main/files/types/assign_nil.gno:6:6: declared and not used: j +// main/assign_nil.gno:7:5: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil.gno:6:6: declared and not used: j diff --git a/gnovm/tests/files/types/assign_nil2.gno b/gnovm/tests/files/types/assign_nil2.gno index a193f6897a5..3821ed56de8 100644 --- a/gnovm/tests/files/types/assign_nil2.gno +++ b/gnovm/tests/files/types/assign_nil2.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/assign_nil2.gno:7:2: cannot assign to uverse nil +// main/assign_nil2.gno:7:2: cannot assign to uverse nil // TypeCheckError: -// main/files/types/assign_nil2.gno:7:2: cannot assign to nil (neither addressable nor a map index expression); main/files/types/assign_nil2.gno:7:7: cannot assign to nil (neither addressable nor a map index expression); main/files/types/assign_nil2.gno:6:6: declared and not used: ok +// main/assign_nil2.gno:7:2: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil2.gno:7:7: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil2.gno:6:6: declared and not used: ok diff --git a/gnovm/tests/files/types/assign_range_a.gno b/gnovm/tests/files/types/assign_range_a.gno index 6e540c1d467..49ee015c40b 100644 --- a/gnovm/tests/files/types/assign_range_a.gno +++ b/gnovm/tests/files/types/assign_range_a.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/types/assign_range_a.gno:16:2: cannot use string as int +// main/assign_range_a.gno:16:2: cannot use string as int // TypeCheckError: -// main/files/types/assign_range_a.gno:16:6: cannot use k (value of type string) as int value in assignment +// main/assign_range_a.gno:16:6: cannot use k (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_a1.gno b/gnovm/tests/files/types/assign_range_a1.gno index 0d59d9acf70..0d6cdb41d54 100644 --- a/gnovm/tests/files/types/assign_range_a1.gno +++ b/gnovm/tests/files/types/assign_range_a1.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/types/assign_range_a1.gno:16:2: cannot assign to (const (6 bigint)) +// main/assign_range_a1.gno:16:2: cannot assign to (const (6 bigint)) // TypeCheckError: -// main/files/types/assign_range_a1.gno:16:6: cannot assign to 6 (neither addressable nor a map index expression) +// main/assign_range_a1.gno:16:6: cannot assign to 6 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_range_b.gno b/gnovm/tests/files/types/assign_range_b.gno index cd99fdb55cf..55fa436c2a0 100644 --- a/gnovm/tests/files/types/assign_range_b.gno +++ b/gnovm/tests/files/types/assign_range_b.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/assign_range_b.gno:14:2: cannot use string as int +// main/assign_range_b.gno:14:2: cannot use string as int // TypeCheckError: -// main/files/types/assign_range_b.gno:14:9: cannot use v (value of type string) as int value in assignment +// main/assign_range_b.gno:14:9: cannot use v (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_b1.gno b/gnovm/tests/files/types/assign_range_b1.gno index 906dbd03fce..2c6f91820a9 100644 --- a/gnovm/tests/files/types/assign_range_b1.gno +++ b/gnovm/tests/files/types/assign_range_b1.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/assign_range_b1.gno:14:2: cannot use string as int +// main/assign_range_b1.gno:14:2: cannot use string as int // TypeCheckError: -// main/files/types/assign_range_b1.gno:14:9: cannot use v (value of type string) as int value in assignment +// main/assign_range_b1.gno:14:9: cannot use v (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_c.gno b/gnovm/tests/files/types/assign_range_c.gno index f813c7a9f14..ee9e5379006 100644 --- a/gnovm/tests/files/types/assign_range_c.gno +++ b/gnovm/tests/files/types/assign_range_c.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/assign_range_c.gno:14:2: index type should be int, but got float32 +// main/assign_range_c.gno:14:2: index type should be int, but got float32 // TypeCheckError: -// main/files/types/assign_range_c.gno:14:6: cannot use k (value of type int) as float32 value in assignment; main/files/types/assign_range_c.gno:14:9: cannot use v (value of type string) as float32 value in assignment +// main/assign_range_c.gno:14:6: cannot use k (value of type int) as float32 value in assignment; main/assign_range_c.gno:14:9: cannot use v (value of type string) as float32 value in assignment diff --git a/gnovm/tests/files/types/assign_range_d.gno b/gnovm/tests/files/types/assign_range_d.gno index 92753e16d99..d3b07d8d3b6 100644 --- a/gnovm/tests/files/types/assign_range_d.gno +++ b/gnovm/tests/files/types/assign_range_d.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/assign_range_d.gno:8:2: index type should be int, but got float32 +// main/assign_range_d.gno:8:2: index type should be int, but got float32 // TypeCheckError: -// main/files/types/assign_range_d.gno:8:6: cannot use index (value of type int) as float32 value in assignment; main/files/types/assign_range_d.gno:7:6: declared and not used: value +// main/assign_range_d.gno:8:6: cannot use index (value of type int) as float32 value in assignment; main/assign_range_d.gno:7:6: declared and not used: value diff --git a/gnovm/tests/files/types/assign_range_e.gno b/gnovm/tests/files/types/assign_range_e.gno index e7807737ef0..ca00cf658f5 100644 --- a/gnovm/tests/files/types/assign_range_e.gno +++ b/gnovm/tests/files/types/assign_range_e.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/types/assign_range_e.gno:8:2: value type should be int32, but got int +// main/assign_range_e.gno:8:2: value type should be int32, but got int // TypeCheckError: -// main/files/types/assign_range_e.gno:8:13: cannot use value (value of type rune) as int value in assignment +// main/assign_range_e.gno:8:13: cannot use value (value of type rune) as int value in assignment diff --git a/gnovm/tests/files/types/assign_rune_a.gno b/gnovm/tests/files/types/assign_rune_a.gno index 7447a6907fd..4e3a1db4ac6 100644 --- a/gnovm/tests/files/types/assign_rune_a.gno +++ b/gnovm/tests/files/types/assign_rune_a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/assign_rune_a.gno:7:2: cannot use untyped string as Int32Kind +// main/assign_rune_a.gno:7:2: cannot use untyped string as Int32Kind // TypeCheckError: -// main/files/types/assign_rune_a.gno:7:6: cannot use "a" (untyped string constant) as rune value in assignment +// main/assign_rune_a.gno:7:6: cannot use "a" (untyped string constant) as rune value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion.gno b/gnovm/tests/files/types/assign_type_assertion.gno index 58a5deeab26..52fd842f36f 100644 --- a/gnovm/tests/files/types/assign_type_assertion.gno +++ b/gnovm/tests/files/types/assign_type_assertion.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion.gno:13:2: cannot use string as int +// main/assign_type_assertion.gno:13:2: cannot use string as int // TypeCheckError: -// main/files/types/assign_type_assertion.gno:13:10: cannot use i.(string) (comma, ok expression of type string) as int value in assignment +// main/assign_type_assertion.gno:13:10: cannot use i.(string) (comma, ok expression of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_b.gno b/gnovm/tests/files/types/assign_type_assertion_b.gno index 5f739fc0529..f0189b6e752 100644 --- a/gnovm/tests/files/types/assign_type_assertion_b.gno +++ b/gnovm/tests/files/types/assign_type_assertion_b.gno @@ -29,7 +29,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_b.gno:22:2: cannot use interface {IsSet func() bool} as int +// main/assign_type_assertion_b.gno:22:2: cannot use interface {IsSet func() bool} as int // TypeCheckError: -// main/files/types/assign_type_assertion_b.gno:22:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as int value in assignment; main/files/types/assign_type_assertion_b.gno:25:37: assertedErr.IsSet undefined (type int has no field or method IsSet) +// main/assign_type_assertion_b.gno:22:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as int value in assignment; main/assign_type_assertion_b.gno:25:37: assertedErr.IsSet undefined (type int has no field or method IsSet) diff --git a/gnovm/tests/files/types/assign_type_assertion_c.gno b/gnovm/tests/files/types/assign_type_assertion_c.gno index 1d632090650..00d8b4bf380 100644 --- a/gnovm/tests/files/types/assign_type_assertion_c.gno +++ b/gnovm/tests/files/types/assign_type_assertion_c.gno @@ -30,7 +30,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_c.gno:23:2: interface {IsSet func() bool} does not implement interface {IsNotSet func() bool} (missing method IsNotSet) +// main/assign_type_assertion_c.gno:23:2: interface {IsSet func() bool} does not implement interface {IsNotSet func() bool} (missing method IsNotSet) // TypeCheckError: -// main/files/types/assign_type_assertion_c.gno:23:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as interface{IsNotSet() bool} value in assignment: interface{IsSet() bool} does not implement interface{IsNotSet() bool} (missing method IsNotSet); main/files/types/assign_type_assertion_c.gno:26:37: assertedErr.IsSet undefined (type interface{IsNotSet() bool} has no field or method IsSet) +// main/assign_type_assertion_c.gno:23:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as interface{IsNotSet() bool} value in assignment: interface{IsSet() bool} does not implement interface{IsNotSet() bool} (missing method IsNotSet); main/assign_type_assertion_c.gno:26:37: assertedErr.IsSet undefined (type interface{IsNotSet() bool} has no field or method IsSet) diff --git a/gnovm/tests/files/types/assign_type_assertion_d.gno b/gnovm/tests/files/types/assign_type_assertion_d.gno index 30585ab524f..23f940a0ebd 100644 --- a/gnovm/tests/files/types/assign_type_assertion_d.gno +++ b/gnovm/tests/files/types/assign_type_assertion_d.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_d.gno:19:2: cannot use main.Dog as main.Robot without explicit conversion +// main/assign_type_assertion_d.gno:19:2: cannot use main.Dog as main.Robot without explicit conversion // TypeCheckError: -// main/files/types/assign_type_assertion_d.gno:19:6: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment +// main/assign_type_assertion_d.gno:19:6: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_e.gno b/gnovm/tests/files/types/assign_type_assertion_e.gno index d00c6cd00aa..346e6404159 100644 --- a/gnovm/tests/files/types/assign_type_assertion_e.gno +++ b/gnovm/tests/files/types/assign_type_assertion_e.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_e.gno:20:2: cannot use main.Dog as main.Robot without explicit conversion +// main/assign_type_assertion_e.gno:20:2: cannot use main.Dog as main.Robot without explicit conversion // TypeCheckError: -// main/files/types/assign_type_assertion_e.gno:20:10: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment +// main/assign_type_assertion_e.gno:20:10: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_f.gno b/gnovm/tests/files/types/assign_type_assertion_f.gno index 9e45447d105..7fe443ffc33 100644 --- a/gnovm/tests/files/types/assign_type_assertion_f.gno +++ b/gnovm/tests/files/types/assign_type_assertion_f.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_f.gno:19:2: cannot assign to (const (1 bigint)) +// main/assign_type_assertion_f.gno:19:2: cannot assign to (const (1 bigint)) // TypeCheckError: -// main/files/types/assign_type_assertion_f.gno:19:2: cannot assign to 1 (neither addressable nor a map index expression) +// main/assign_type_assertion_f.gno:19:2: cannot assign to 1 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_type_assertion_g.gno b/gnovm/tests/files/types/assign_type_assertion_g.gno index c98d76ba762..358fab8aec5 100644 --- a/gnovm/tests/files/types/assign_type_assertion_g.gno +++ b/gnovm/tests/files/types/assign_type_assertion_g.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_g.gno:20:2: want bool type got int +// main/assign_type_assertion_g.gno:20:2: want bool type got int // TypeCheckError: -// main/files/types/assign_type_assertion_g.gno:20:10: cannot use animal.(Dog) (untyped bool value) as int value in assignment +// main/assign_type_assertion_g.gno:20:10: cannot use animal.(Dog) (untyped bool value) as int value in assignment diff --git a/gnovm/tests/files/types/bigdec2.gno b/gnovm/tests/files/types/bigdec2.gno index 65930d2b17d..94c0b3edd6f 100644 --- a/gnovm/tests/files/types/bigdec2.gno +++ b/gnovm/tests/files/types/bigdec2.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/bigdec2.gno:7:10: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/bigdec2.gno:7:10: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: -// main/files/types/bigdec2.gno:7:14: 1.2 (untyped float constant) truncated to uint64 +// main/bigdec2.gno:7:14: 1.2 (untyped float constant) truncated to uint64 diff --git a/gnovm/tests/files/types/bigdec5.gno b/gnovm/tests/files/types/bigdec5.gno index 51cb40cff3c..57a8d20bc91 100644 --- a/gnovm/tests/files/types/bigdec5.gno +++ b/gnovm/tests/files/types/bigdec5.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/bigdec5.gno:6:2: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/bigdec5.gno:6:2: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: -// main/files/types/bigdec5.gno:6:6: cannot use 1.2 (untyped float constant) as uint64 value in assignment (truncated) +// main/bigdec5.gno:6:6: cannot use 1.2 (untyped float constant) as uint64 value in assignment (truncated) diff --git a/gnovm/tests/files/types/bigdec_6.gno b/gnovm/tests/files/types/bigdec_6.gno index 8f9c309c535..ca3af93c77c 100644 --- a/gnovm/tests/files/types/bigdec_6.gno +++ b/gnovm/tests/files/types/bigdec_6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/bigdec_6.gno:4:10: operator % not defined on: BigdecKind +// main/bigdec_6.gno:4:10: operator % not defined on: BigdecKind // TypeCheckError: -// main/files/types/bigdec_6.gno:4:10: invalid operation: operator % not defined on 1 (untyped float constant) +// main/bigdec_6.gno:4:10: invalid operation: operator % not defined on 1 (untyped float constant) diff --git a/gnovm/tests/files/types/cmp_array_b.gno b/gnovm/tests/files/types/cmp_array_b.gno index ea0880233cf..80cd39fe112 100644 --- a/gnovm/tests/files/types/cmp_array_b.gno +++ b/gnovm/tests/files/types/cmp_array_b.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/types/cmp_array_b.gno:10:25: [2][]int is not comparable +// main/cmp_array_b.gno:10:25: [2][]int is not comparable // TypeCheckError: -// main/files/types/cmp_array_b.gno:10:25: invalid operation: a == b ([2][]int cannot be compared); main/files/types/cmp_array_b.gno:11:25: invalid operation: a == c ([2][]int cannot be compared) +// main/cmp_array_b.gno:10:25: invalid operation: a == b ([2][]int cannot be compared); main/cmp_array_b.gno:11:25: invalid operation: a == c ([2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_array_c.gno b/gnovm/tests/files/types/cmp_array_c.gno index 00e7d6b2320..7db78799800 100644 --- a/gnovm/tests/files/types/cmp_array_c.gno +++ b/gnovm/tests/files/types/cmp_array_c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/types/cmp_array_c.gno:10:25: [2][]int is not comparable +// main/cmp_array_c.gno:10:25: [2][]int is not comparable // TypeCheckError: -// main/files/types/cmp_array_c.gno:10:25: invalid operation: a == b ([2][2][]int cannot be compared); main/files/types/cmp_array_c.gno:11:25: invalid operation: a == c ([2][2][]int cannot be compared) +// main/cmp_array_c.gno:10:25: invalid operation: a == b ([2][2][]int cannot be compared); main/cmp_array_c.gno:11:25: invalid operation: a == c ([2][2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_iface_5.gno b/gnovm/tests/files/types/cmp_iface_5.gno index b4c8853f151..350c6ea50cf 100644 --- a/gnovm/tests/files/types/cmp_iface_5.gno +++ b/gnovm/tests/files/types/cmp_iface_5.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/cmp_iface_5.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/cmp_iface_5.gno:19:5: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/cmp_iface_5.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) +// main/cmp_iface_5.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno index 5427c0aeac2..e9e10e1c5ed 100644 --- a/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno +++ b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/cmp_iface_5_stdlibs.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/cmp_iface_5_stdlibs.gno:19:5: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/cmp_iface_5_stdlibs.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) +// main/cmp_iface_5_stdlibs.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/cmp_pointer.gno b/gnovm/tests/files/types/cmp_pointer.gno index 3a942246d7c..79f6b173eea 100644 --- a/gnovm/tests/files/types/cmp_pointer.gno +++ b/gnovm/tests/files/types/cmp_pointer.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/cmp_pointer.gno:19:27: cannot use main.Person as main.Worker without explicit conversion +// main/cmp_pointer.gno:19:27: cannot use main.Person as main.Worker without explicit conversion // TypeCheckError: -// main/files/types/cmp_pointer.gno:19:33: invalid operation: p1 == p2Ptr (mismatched types *Person and *Worker) +// main/cmp_pointer.gno:19:33: invalid operation: p1 == p2Ptr (mismatched types *Person and *Worker) diff --git a/gnovm/tests/files/types/cmp_primitive_1.gno b/gnovm/tests/files/types/cmp_primitive_1.gno index fedb5d5a041..29395c742e7 100644 --- a/gnovm/tests/files/types/cmp_primitive_1.gno +++ b/gnovm/tests/files/types/cmp_primitive_1.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/types/cmp_primitive_1.gno:14:5: cannot use untyped Bigint as StringKind +// main/cmp_primitive_1.gno:14:5: cannot use untyped Bigint as StringKind // TypeCheckError: -// main/files/types/cmp_primitive_1.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) +// main/cmp_primitive_1.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) diff --git a/gnovm/tests/files/types/cmp_slice_4.gno b/gnovm/tests/files/types/cmp_slice_4.gno index 5c2498ba365..45845d69d0a 100644 --- a/gnovm/tests/files/types/cmp_slice_4.gno +++ b/gnovm/tests/files/types/cmp_slice_4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/cmp_slice_4.gno:6:10: cannot use int as string +// main/cmp_slice_4.gno:6:10: cannot use int as string // TypeCheckError: -// main/files/types/cmp_slice_4.gno:6:15: invalid operation: a == expected (mismatched types int and string) +// main/cmp_slice_4.gno:6:15: invalid operation: a == expected (mismatched types int and string) diff --git a/gnovm/tests/files/types/cmp_struct_a.gno b/gnovm/tests/files/types/cmp_struct_a.gno index a7e9fd70e90..74b6865ee11 100644 --- a/gnovm/tests/files/types/cmp_struct_a.gno +++ b/gnovm/tests/files/types/cmp_struct_a.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_a.gno:15:25: [2][]int is not comparable +// main/cmp_struct_a.gno:15:25: [2][]int is not comparable // TypeCheckError: -// main/files/types/cmp_struct_a.gno:15:25: invalid operation: a == b (struct containing [2][2][]int cannot be compared); main/files/types/cmp_struct_a.gno:16:25: invalid operation: a == c (struct containing [2][2][]int cannot be compared) +// main/cmp_struct_a.gno:15:25: invalid operation: a == b (struct containing [2][2][]int cannot be compared); main/cmp_struct_a.gno:16:25: invalid operation: a == c (struct containing [2][2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_struct_b.gno b/gnovm/tests/files/types/cmp_struct_b.gno index d6f05125218..8d1ae12ca8b 100644 --- a/gnovm/tests/files/types/cmp_struct_b.gno +++ b/gnovm/tests/files/types/cmp_struct_b.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_b.gno:15:10: cannot use main.foo as main.bar without explicit conversion +// main/cmp_struct_b.gno:15:10: cannot use main.foo as main.bar without explicit conversion // TypeCheckError: -// main/files/types/cmp_struct_b.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) +// main/cmp_struct_b.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_c.gno b/gnovm/tests/files/types/cmp_struct_c.gno index 4e97f3c0248..769d217eeb4 100644 --- a/gnovm/tests/files/types/cmp_struct_c.gno +++ b/gnovm/tests/files/types/cmp_struct_c.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_c.gno:15:10: main.bar is not comparable +// main/cmp_struct_c.gno:15:10: main.bar is not comparable // TypeCheckError: -// main/files/types/cmp_struct_c.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) +// main/cmp_struct_c.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_c1.gno b/gnovm/tests/files/types/cmp_struct_c1.gno index 41180ba75c7..b09f14c116f 100644 --- a/gnovm/tests/files/types/cmp_struct_c1.gno +++ b/gnovm/tests/files/types/cmp_struct_c1.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_c1.gno:15:10: cannot use main.bar as main.foo without explicit conversion +// main/cmp_struct_c1.gno:15:10: cannot use main.bar as main.foo without explicit conversion // TypeCheckError: -// main/files/types/cmp_struct_c1.gno:15:16: invalid operation: bb == fa (mismatched types bar and foo) +// main/cmp_struct_c1.gno:15:16: invalid operation: bb == fa (mismatched types bar and foo) diff --git a/gnovm/tests/files/types/cmp_struct_d.gno b/gnovm/tests/files/types/cmp_struct_d.gno index a4342085028..a7388d83d67 100644 --- a/gnovm/tests/files/types/cmp_struct_d.gno +++ b/gnovm/tests/files/types/cmp_struct_d.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_d.gno:15:10: main.bar is not comparable +// main/cmp_struct_d.gno:15:10: main.bar is not comparable // TypeCheckError: -// main/files/types/cmp_struct_d.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) +// main/cmp_struct_d.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_e.gno b/gnovm/tests/files/types/cmp_struct_e.gno index 19d855b24d1..9cb878548e4 100644 --- a/gnovm/tests/files/types/cmp_struct_e.gno +++ b/gnovm/tests/files/types/cmp_struct_e.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_e.gno:11:10: main.foo is not comparable +// main/cmp_struct_e.gno:11:10: main.foo is not comparable // TypeCheckError: -// main/files/types/cmp_struct_e.gno:11:10: invalid operation: fa == fb (struct containing []int cannot be compared) +// main/cmp_struct_e.gno:11:10: invalid operation: fa == fb (struct containing []int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_struct_g.gno b/gnovm/tests/files/types/cmp_struct_g.gno index 7c89f8b0ed2..8868515deec 100644 --- a/gnovm/tests/files/types/cmp_struct_g.gno +++ b/gnovm/tests/files/types/cmp_struct_g.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/files/types/cmp_struct_g.gno:17:25: cannot use main.Person as main.Dog without explicit conversion +// main/cmp_struct_g.gno:17:25: cannot use main.Person as main.Dog without explicit conversion // TypeCheckError: -// main/files/types/cmp_struct_g.gno:17:30: invalid operation: a == b (mismatched types Person and Dog) +// main/cmp_struct_g.gno:17:30: invalid operation: a == b (mismatched types Person and Dog) diff --git a/gnovm/tests/files/types/eql_0a0.gno b/gnovm/tests/files/types/eql_0a0.gno index ba96e18f779..912039e9e14 100644 --- a/gnovm/tests/files/types/eql_0a0.gno +++ b/gnovm/tests/files/types/eql_0a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/eql_0a0.gno:5:10: cannot use int as int8 +// main/eql_0a0.gno:5:10: cannot use int as int8 // TypeCheckError: -// main/files/types/eql_0a0.gno:5:20: invalid operation: int(1) == int8(1) (mismatched types int and int8) +// main/eql_0a0.gno:5:20: invalid operation: int(1) == int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/eql_0a01.gno b/gnovm/tests/files/types/eql_0a01.gno index 1061b3022dd..632a0675cc1 100644 --- a/gnovm/tests/files/types/eql_0a01.gno +++ b/gnovm/tests/files/types/eql_0a01.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/eql_0a01.gno:4:10: is not comparable +// main/eql_0a01.gno:4:10: is not comparable // TypeCheckError: -// main/files/types/eql_0a01.gno:4:17: invalid operation: nil == nil (operator == not defined on untyped nil) +// main/eql_0a01.gno:4:17: invalid operation: nil == nil (operator == not defined on untyped nil) diff --git a/gnovm/tests/files/types/eql_0a02.gno b/gnovm/tests/files/types/eql_0a02.gno index 36e73c5652e..167169ca770 100644 --- a/gnovm/tests/files/types/eql_0a02.gno +++ b/gnovm/tests/files/types/eql_0a02.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/eql_0a02.gno:7:10: cannot use *int as string +// main/eql_0a02.gno:7:10: cannot use *int as string // TypeCheckError: -// main/files/types/eql_0a02.gno:7:20: invalid operation: intPtr == s (mismatched types *int and string) +// main/eql_0a02.gno:7:20: invalid operation: intPtr == s (mismatched types *int and string) diff --git a/gnovm/tests/files/types/eql_0a03.gno b/gnovm/tests/files/types/eql_0a03.gno index 2b982693f07..916e3efe5d2 100644 --- a/gnovm/tests/files/types/eql_0a03.gno +++ b/gnovm/tests/files/types/eql_0a03.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/eql_0a03.gno:8:10: cannot use int8 as int +// main/eql_0a03.gno:8:10: cannot use int8 as int // TypeCheckError: -// main/files/types/eql_0a03.gno:8:20: invalid operation: intPtr == &i (mismatched types *int8 and *int) +// main/eql_0a03.gno:8:20: invalid operation: intPtr == &i (mismatched types *int8 and *int) diff --git a/gnovm/tests/files/types/eql_0a1.gno b/gnovm/tests/files/types/eql_0a1.gno index 881e7d795b2..a25380793f4 100644 --- a/gnovm/tests/files/types/eql_0a1.gno +++ b/gnovm/tests/files/types/eql_0a1.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/eql_0a1.gno:5:10: cannot use int as int8 +// main/eql_0a1.gno:5:10: cannot use int as int8 // TypeCheckError: -// main/files/types/eql_0a1.gno:5:20: invalid operation: int(1) != int8(1) (mismatched types int and int8) +// main/eql_0a1.gno:5:20: invalid operation: int(1) != int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/eql_0a1a0.gno b/gnovm/tests/files/types/eql_0a1a0.gno index b9cf9aa44ec..f2f5c335f6f 100644 --- a/gnovm/tests/files/types/eql_0a1a0.gno +++ b/gnovm/tests/files/types/eql_0a1a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/eql_0a1a0.gno:5:10: cannot use uint64 as uint +// main/eql_0a1a0.gno:5:10: cannot use uint64 as uint // TypeCheckError: -// main/files/types/eql_0a1a0.gno:5:23: invalid operation: uint64(1) == a (mismatched types uint64 and uint) +// main/eql_0a1a0.gno:5:23: invalid operation: uint64(1) == a (mismatched types uint64 and uint) diff --git a/gnovm/tests/files/types/eql_0a1a1.gno b/gnovm/tests/files/types/eql_0a1a1.gno index 90c8373c965..8d90071bc54 100644 --- a/gnovm/tests/files/types/eql_0a1a1.gno +++ b/gnovm/tests/files/types/eql_0a1a1.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/eql_0a1a1.gno:5:10: cannot use uint as uint64 +// main/eql_0a1a1.gno:5:10: cannot use uint as uint64 // TypeCheckError: -// main/files/types/eql_0a1a1.gno:5:15: invalid operation: a == uint64(1) (mismatched types uint and uint64) +// main/eql_0a1a1.gno:5:15: invalid operation: a == uint64(1) (mismatched types uint and uint64) diff --git a/gnovm/tests/files/types/eql_0a1f.gno b/gnovm/tests/files/types/eql_0a1f.gno index 5a6972ea05b..e9062a74869 100644 --- a/gnovm/tests/files/types/eql_0a1f.gno +++ b/gnovm/tests/files/types/eql_0a1f.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/eql_0a1f.gno:6:10: cannot use int as string +// main/eql_0a1f.gno:6:10: cannot use int as string // TypeCheckError: -// main/files/types/eql_0a1f.gno:6:15: invalid operation: a == expected (mismatched types int and string) +// main/eql_0a1f.gno:6:15: invalid operation: a == expected (mismatched types int and string) diff --git a/gnovm/tests/files/types/eql_0a1g.gno b/gnovm/tests/files/types/eql_0a1g.gno index 7b0c3ffb308..1c1f4e3df15 100644 --- a/gnovm/tests/files/types/eql_0a1g.gno +++ b/gnovm/tests/files/types/eql_0a1g.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/eql_0a1g.gno:6:10: cannot use int as float32 +// main/eql_0a1g.gno:6:10: cannot use int as float32 // TypeCheckError: -// main/files/types/eql_0a1g.gno:6:15: invalid operation: a == b (mismatched types int and float32) +// main/eql_0a1g.gno:6:15: invalid operation: a == b (mismatched types int and float32) diff --git a/gnovm/tests/files/types/eql_0a2.gno b/gnovm/tests/files/types/eql_0a2.gno index a60fec4bd98..5954e1fff6b 100644 --- a/gnovm/tests/files/types/eql_0a2.gno +++ b/gnovm/tests/files/types/eql_0a2.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/eql_0a2.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a2.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: -// main/files/types/eql_0a2.gno:21:23: invalid operation: Error1(0) == Error2(0) (mismatched types Error1 and Error2) +// main/eql_0a2.gno:21:23: invalid operation: Error1(0) == Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0a3.gno b/gnovm/tests/files/types/eql_0a3.gno index c14d65ed318..f2120fec151 100644 --- a/gnovm/tests/files/types/eql_0a3.gno +++ b/gnovm/tests/files/types/eql_0a3.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/eql_0a3.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a3.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: -// main/files/types/eql_0a3.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) +// main/eql_0a3.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0a4.gno b/gnovm/tests/files/types/eql_0a4.gno index b86e1c6d985..77be98555cd 100644 --- a/gnovm/tests/files/types/eql_0a4.gno +++ b/gnovm/tests/files/types/eql_0a4.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/eql_0a4.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a4.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: -// main/files/types/eql_0a4.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) +// main/eql_0a4.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0b2.gno b/gnovm/tests/files/types/eql_0b2.gno index b4eef7012c8..7e5cfabda20 100644 --- a/gnovm/tests/files/types/eql_0b2.gno +++ b/gnovm/tests/files/types/eql_0b2.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/files/types/eql_0b2.gno:14:5: cannot use untyped Bigint as StringKind +// main/eql_0b2.gno:14:5: cannot use untyped Bigint as StringKind // TypeCheckError: -// main/files/types/eql_0b2.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) +// main/eql_0b2.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) diff --git a/gnovm/tests/files/types/eql_0b4.gno b/gnovm/tests/files/types/eql_0b4.gno index 6d0570075e4..9cab0f59c20 100644 --- a/gnovm/tests/files/types/eql_0b4.gno +++ b/gnovm/tests/files/types/eql_0b4.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/eql_0b4.gno:9:10: bigint does not implement .uverse.error (missing method Error) +// main/eql_0b4.gno:9:10: bigint does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/eql_0b4.gno:9:10: cannot convert 5 (untyped int constant) to type interface{Error() string} +// main/eql_0b4.gno:9:10: cannot convert 5 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/eql_0c2.gno b/gnovm/tests/files/types/eql_0c2.gno index d264598303d..b51f8aeb902 100644 --- a/gnovm/tests/files/types/eql_0c2.gno +++ b/gnovm/tests/files/types/eql_0c2.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/files/types/eql_0c2.gno:16:5: bigint overflows target kind +// main/eql_0c2.gno:16:5: bigint overflows target kind // TypeCheckError: -// main/files/types/eql_0c2.gno:16:17: 128 (untyped int constant) overflows int8 +// main/eql_0c2.gno:16:17: 128 (untyped int constant) overflows int8 diff --git a/gnovm/tests/files/types/eql_0e0.gno b/gnovm/tests/files/types/eql_0e0.gno index f0977ef56bb..0e0220ed396 100644 --- a/gnovm/tests/files/types/eql_0e0.gno +++ b/gnovm/tests/files/types/eql_0e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/eql_0e0.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0e0.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: -// main/files/types/eql_0e0.gno:23:16: invalid operation: e1 == e2 (mismatched types Error1 and Error2) +// main/eql_0e0.gno:23:16: invalid operation: e1 == e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0e1.gno b/gnovm/tests/files/types/eql_0e1.gno index 2b93c02288d..121e57a8017 100644 --- a/gnovm/tests/files/types/eql_0e1.gno +++ b/gnovm/tests/files/types/eql_0e1.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/eql_0e1.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0e1.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: -// main/files/types/eql_0e1.gno:23:16: invalid operation: e1 != e2 (mismatched types Error1 and Error2) +// main/eql_0e1.gno:23:16: invalid operation: e1 != e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0f0.gno b/gnovm/tests/files/types/eql_0f0.gno index 5b854894c49..11ab657488d 100644 --- a/gnovm/tests/files/types/eql_0f0.gno +++ b/gnovm/tests/files/types/eql_0f0.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/eql_0f0.gno:19:5: bigint does not implement .uverse.error (missing method Error) +// main/eql_0f0.gno:19:5: bigint does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/eql_0f0.gno:19:5: cannot convert 1 (untyped int constant) to type interface{Error() string} +// main/eql_0f0.gno:19:5: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/eql_0f1.gno b/gnovm/tests/files/types/eql_0f1.gno index 88084a1fa86..4073d4c5db2 100644 --- a/gnovm/tests/files/types/eql_0f1.gno +++ b/gnovm/tests/files/types/eql_0f1.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/eql_0f1.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/eql_0f1.gno:19:5: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/eql_0f1.gno:19:17: invalid operation: int64(1) == errCmp (mismatched types int64 and error) +// main/eql_0f1.gno:19:17: invalid operation: int64(1) == errCmp (mismatched types int64 and error) diff --git a/gnovm/tests/files/types/eql_0f14.gno b/gnovm/tests/files/types/eql_0f14.gno index 2db524df181..cf30a3a6fc7 100644 --- a/gnovm/tests/files/types/eql_0f14.gno +++ b/gnovm/tests/files/types/eql_0f14.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/eql_0f14.gno:10:10: cannot use [2]string as [2]int +// main/eql_0f14.gno:10:10: cannot use [2]string as [2]int // TypeCheckError: -// main/files/types/eql_0f14.gno:10:15: invalid operation: a == c (mismatched types [2]string and [2]int) +// main/eql_0f14.gno:10:15: invalid operation: a == c (mismatched types [2]string and [2]int) diff --git a/gnovm/tests/files/types/eql_0f16.gno b/gnovm/tests/files/types/eql_0f16.gno index 3a58ff16c36..19fa2cccd3a 100644 --- a/gnovm/tests/files/types/eql_0f16.gno +++ b/gnovm/tests/files/types/eql_0f16.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/files/types/eql_0f16.gno:16:10: [2]main.word is not comparable +// main/eql_0f16.gno:16:10: [2]main.word is not comparable // TypeCheckError: -// main/files/types/eql_0f16.gno:16:10: invalid operation: a == c ([2]word cannot be compared) +// main/eql_0f16.gno:16:10: invalid operation: a == c ([2]word cannot be compared) diff --git a/gnovm/tests/files/types/eql_0f17.gno b/gnovm/tests/files/types/eql_0f17.gno index f1f44fa7001..b71cab3209e 100644 --- a/gnovm/tests/files/types/eql_0f17.gno +++ b/gnovm/tests/files/types/eql_0f17.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/eql_0f17.gno:9:10: main.f can only be compared to nil +// main/eql_0f17.gno:9:10: main.f can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f17.gno:9:10: invalid operation: a == b (func can only be compared to nil) +// main/eql_0f17.gno:9:10: invalid operation: a == b (func can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f20.gno b/gnovm/tests/files/types/eql_0f20.gno index da337c4d7c9..b752c922410 100644 --- a/gnovm/tests/files/types/eql_0f20.gno +++ b/gnovm/tests/files/types/eql_0f20.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/eql_0f20.gno:9:10: [2]main.f is not comparable +// main/eql_0f20.gno:9:10: [2]main.f is not comparable // TypeCheckError: -// main/files/types/eql_0f20.gno:9:15: invalid operation: a == nil (mismatched types [2]f and untyped nil) +// main/eql_0f20.gno:9:15: invalid operation: a == nil (mismatched types [2]f and untyped nil) diff --git a/gnovm/tests/files/types/eql_0f21.gno b/gnovm/tests/files/types/eql_0f21.gno index 1711ee73fd6..433252392b7 100644 --- a/gnovm/tests/files/types/eql_0f21.gno +++ b/gnovm/tests/files/types/eql_0f21.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/eql_0f21.gno:9:10: [2]main.f is not comparable +// main/eql_0f21.gno:9:10: [2]main.f is not comparable // TypeCheckError: -// main/files/types/eql_0f21.gno:9:10: invalid operation: a == b ([2]f cannot be compared) +// main/eql_0f21.gno:9:10: invalid operation: a == b ([2]f cannot be compared) diff --git a/gnovm/tests/files/types/eql_0f27.gno b/gnovm/tests/files/types/eql_0f27.gno index 684272f62b1..324a88c790f 100644 --- a/gnovm/tests/files/types/eql_0f27.gno +++ b/gnovm/tests/files/types/eql_0f27.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/files/types/eql_0f27.gno:13:5: operator > not defined on: InterfaceKind +// main/eql_0f27.gno:13:5: operator > not defined on: InterfaceKind // TypeCheckError: -// main/files/types/eql_0f27.gno:13:5: invalid operation: errCmp1 > errCmp2 (operator > not defined on interface) +// main/eql_0f27.gno:13:5: invalid operation: errCmp1 > errCmp2 (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f28.gno b/gnovm/tests/files/types/eql_0f28.gno index 5b3e3f2c1a2..ad4980b4661 100644 --- a/gnovm/tests/files/types/eql_0f28.gno +++ b/gnovm/tests/files/types/eql_0f28.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/files/types/eql_0f28.gno:27:10: operator > not defined on: InterfaceKind +// main/eql_0f28.gno:27:10: operator > not defined on: InterfaceKind // TypeCheckError: -// main/files/types/eql_0f28.gno:27:10: invalid operation: e1 > e2 (operator > not defined on interface) +// main/eql_0f28.gno:27:10: invalid operation: e1 > e2 (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f29.gno b/gnovm/tests/files/types/eql_0f29.gno index 79dbb8b493c..f15ffa0f7f0 100644 --- a/gnovm/tests/files/types/eql_0f29.gno +++ b/gnovm/tests/files/types/eql_0f29.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/files/types/eql_0f29.gno:16:5: operator > not defined on: InterfaceKind +// main/eql_0f29.gno:16:5: operator > not defined on: InterfaceKind // TypeCheckError: -// main/files/types/eql_0f29.gno:16:5: invalid operation: l > Error(0) (operator > not defined on interface) +// main/eql_0f29.gno:16:5: invalid operation: l > Error(0) (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f2b.gno b/gnovm/tests/files/types/eql_0f2b.gno index 027a52d72ca..fe831661608 100644 --- a/gnovm/tests/files/types/eql_0f2b.gno +++ b/gnovm/tests/files/types/eql_0f2b.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/eql_0f2b.gno:19:5: operator <= not defined on: InterfaceKind +// main/eql_0f2b.gno:19:5: operator <= not defined on: InterfaceKind // TypeCheckError: -// main/files/types/eql_0f2b.gno:19:17: invalid operation: Error(0) <= errCmp (operator <= not defined on interface) +// main/eql_0f2b.gno:19:17: invalid operation: Error(0) <= errCmp (operator <= not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f2c.gno b/gnovm/tests/files/types/eql_0f2c.gno index 4ac5663e8b1..af0f55c4028 100644 --- a/gnovm/tests/files/types/eql_0f2c.gno +++ b/gnovm/tests/files/types/eql_0f2c.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/files/types/eql_0f2c.gno:19:5: operator < not defined on: InterfaceKind +// main/eql_0f2c.gno:19:5: operator < not defined on: InterfaceKind // TypeCheckError: -// main/files/types/eql_0f2c.gno:19:16: invalid operation: Error(0) < errCmp (operator < not defined on interface) +// main/eql_0f2c.gno:19:16: invalid operation: Error(0) < errCmp (operator < not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f30.gno b/gnovm/tests/files/types/eql_0f30.gno index 1fd5ab11c96..c9abe621494 100644 --- a/gnovm/tests/files/types/eql_0f30.gno +++ b/gnovm/tests/files/types/eql_0f30.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/eql_0f30.gno:5:10: []uint8 can only be compared to nil +// main/eql_0f30.gno:5:10: []uint8 can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f30.gno:5:10: invalid operation: []byte("a") == []byte("b") (slice can only be compared to nil) +// main/eql_0f30.gno:5:10: invalid operation: []byte("a") == []byte("b") (slice can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30a.gno b/gnovm/tests/files/types/eql_0f30a.gno index ee628a22b19..26eb4fa28a0 100644 --- a/gnovm/tests/files/types/eql_0f30a.gno +++ b/gnovm/tests/files/types/eql_0f30a.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/eql_0f30a.gno:4:10: map[string]int can only be compared to nil +// main/eql_0f30a.gno:4:10: map[string]int can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f30a.gno:4:10: invalid operation: map[string]int{…} == map[string]int{…} (map can only be compared to nil) +// main/eql_0f30a.gno:4:10: invalid operation: map[string]int{…} == map[string]int{…} (map can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30b.gno b/gnovm/tests/files/types/eql_0f30b.gno index 7e26618d199..00b85e4ebc2 100644 --- a/gnovm/tests/files/types/eql_0f30b.gno +++ b/gnovm/tests/files/types/eql_0f30b.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/eql_0f30b.gno:9:10: main.f can only be compared to nil +// main/eql_0f30b.gno:9:10: main.f can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f30b.gno:9:10: invalid operation: f1 == f2 (func can only be compared to nil) +// main/eql_0f30b.gno:9:10: invalid operation: f1 == f2 (func can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30d.gno b/gnovm/tests/files/types/eql_0f30d.gno index 7360cc117ab..bc501866fbf 100644 --- a/gnovm/tests/files/types/eql_0f30d.gno +++ b/gnovm/tests/files/types/eql_0f30d.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/eql_0f30d.gno:4:10: []int can only be compared to nil +// main/eql_0f30d.gno:4:10: []int can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f30d.gno:4:10: invalid operation: []int{…} == []int{…} (slice can only be compared to nil) +// main/eql_0f30d.gno:4:10: invalid operation: []int{…} == []int{…} (slice can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30f.gno b/gnovm/tests/files/types/eql_0f30f.gno index 1274c70738f..18c582f7fa3 100644 --- a/gnovm/tests/files/types/eql_0f30f.gno +++ b/gnovm/tests/files/types/eql_0f30f.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/eql_0f30f.gno:7:10: cannot use [2]int as [3]int +// main/eql_0f30f.gno:7:10: cannot use [2]int as [3]int // TypeCheckError: -// main/files/types/eql_0f30f.gno:7:15: invalid operation: a == b (mismatched types [2]int and [3]int) +// main/eql_0f30f.gno:7:15: invalid operation: a == b (mismatched types [2]int and [3]int) diff --git a/gnovm/tests/files/types/eql_0f30g.gno b/gnovm/tests/files/types/eql_0f30g.gno index 57df69cd018..b39286ee1df 100644 --- a/gnovm/tests/files/types/eql_0f30g.gno +++ b/gnovm/tests/files/types/eql_0f30g.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/eql_0f30g.gno:7:10: []int can only be compared to nil +// main/eql_0f30g.gno:7:10: []int can only be compared to nil // TypeCheckError: -// main/files/types/eql_0f30g.gno:7:15: invalid operation: a == b (mismatched types [2]int and []int) +// main/eql_0f30g.gno:7:15: invalid operation: a == b (mismatched types [2]int and []int) diff --git a/gnovm/tests/files/types/eql_0f41.gno b/gnovm/tests/files/types/eql_0f41.gno index b00c4b8b906..600b829441a 100644 --- a/gnovm/tests/files/types/eql_0f41.gno +++ b/gnovm/tests/files/types/eql_0f41.gno @@ -32,7 +32,7 @@ func main() { } // Error: -// main/files/types/eql_0f41.gno:27:5: main.animal does not implement .uverse.error (missing method Error) +// main/eql_0f41.gno:27:5: main.animal does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/eql_0f41.gno:27:14: invalid operation: get() == errCmp (mismatched types animal and error) +// main/eql_0f41.gno:27:14: invalid operation: get() == errCmp (mismatched types animal and error) diff --git a/gnovm/tests/files/types/eql_0f8.gno b/gnovm/tests/files/types/eql_0f8.gno index c9f5a795732..8045fddf5a8 100644 --- a/gnovm/tests/files/types/eql_0f8.gno +++ b/gnovm/tests/files/types/eql_0f8.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/eql_0f8.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/eql_0f8.gno:19:5: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: -// main/files/types/eql_0f8.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) +// main/eql_0f8.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/explicit_conversion_1.gno b/gnovm/tests/files/types/explicit_conversion_1.gno index c0d55ecbaa3..8864622a90b 100644 --- a/gnovm/tests/files/types/explicit_conversion_1.gno +++ b/gnovm/tests/files/types/explicit_conversion_1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/explicit_conversion_1.gno:7:11: cannot convert StringKind to UintKind +// main/explicit_conversion_1.gno:7:11: cannot convert StringKind to UintKind // TypeCheckError: -// main/files/types/explicit_conversion_1.gno:7:16: cannot convert string("hello") (constant "hello" of type string) to type uint +// main/explicit_conversion_1.gno:7:16: cannot convert string("hello") (constant "hello" of type string) to type uint diff --git a/gnovm/tests/files/types/incdec_a1.gno b/gnovm/tests/files/types/incdec_a1.gno index 51859d56412..da9d953e902 100644 --- a/gnovm/tests/files/types/incdec_a1.gno +++ b/gnovm/tests/files/types/incdec_a1.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/incdec_a1.gno:5:2: operator ++ not defined on: StringKind +// main/incdec_a1.gno:5:2: operator ++ not defined on: StringKind // TypeCheckError: -// main/files/types/incdec_a1.gno:5:2: invalid operation: a++ (non-numeric type string) +// main/incdec_a1.gno:5:2: invalid operation: a++ (non-numeric type string) diff --git a/gnovm/tests/files/types/incdec_a4.gno b/gnovm/tests/files/types/incdec_a4.gno index 265882cdf43..4d845e10233 100644 --- a/gnovm/tests/files/types/incdec_a4.gno +++ b/gnovm/tests/files/types/incdec_a4.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/files/types/incdec_a4.gno:12:2: cannot use int8 as main.Int without explicit conversion +// main/incdec_a4.gno:12:2: cannot use int8 as main.Int without explicit conversion // TypeCheckError: -// main/files/types/incdec_a4.gno:12:6: cannot use int8(0) (constant 0 of type int8) as Int value in assignment +// main/incdec_a4.gno:12:6: cannot use int8(0) (constant 0 of type int8) as Int value in assignment diff --git a/gnovm/tests/files/types/nil.gno b/gnovm/tests/files/types/nil.gno index 48020635c4c..6e9839541f3 100644 --- a/gnovm/tests/files/types/nil.gno +++ b/gnovm/tests/files/types/nil.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/nil.gno:5:10: operator + not defined on: nil +// main/nil.gno:5:10: operator + not defined on: nil // TypeCheckError: -// main/files/types/nil.gno:5:10: invalid operation: operator + not defined on nil +// main/nil.gno:5:10: invalid operation: operator + not defined on nil diff --git a/gnovm/tests/files/types/or_a0.gno b/gnovm/tests/files/types/or_a0.gno index efa9079e88c..6ded1ca25f8 100644 --- a/gnovm/tests/files/types/or_a0.gno +++ b/gnovm/tests/files/types/or_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/or_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/or_a0.gno:5:10: invalid operation: mismatched types int and int8 // TypeCheckError: -// main/files/types/or_a0.gno:5:10: invalid operation: int(0) | int8(1) (mismatched types int and int8) +// main/or_a0.gno:5:10: invalid operation: int(0) | int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/or_a1.gno b/gnovm/tests/files/types/or_a1.gno index 2185f04e5fe..d21bad7643f 100644 --- a/gnovm/tests/files/types/or_a1.gno +++ b/gnovm/tests/files/types/or_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/or_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/or_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/or_a1.gno:21:10: invalid operation: Error1(0) | Error2(0) (mismatched types Error1 and Error2) +// main/or_a1.gno:21:10: invalid operation: Error1(0) | Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_b2.gno b/gnovm/tests/files/types/or_b2.gno index 11ccb6460b3..110352eb03c 100644 --- a/gnovm/tests/files/types/or_b2.gno +++ b/gnovm/tests/files/types/or_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/or_b2.gno:5:10: operator | not defined on: StringKind +// main/or_b2.gno:5:10: operator | not defined on: StringKind // TypeCheckError: -// main/files/types/or_b2.gno:5:10: invalid operation: 1 | "a" (mismatched types untyped int and untyped string) +// main/or_b2.gno:5:10: invalid operation: 1 | "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/or_b3.gno b/gnovm/tests/files/types/or_b3.gno index 29bcb070407..65ba5b02c18 100644 --- a/gnovm/tests/files/types/or_b3.gno +++ b/gnovm/tests/files/types/or_b3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/or_b3.gno:5:10: operator | not defined on: StringKind +// main/or_b3.gno:5:10: operator | not defined on: StringKind // TypeCheckError: -// main/files/types/or_b3.gno:5:10: invalid operation: operator | not defined on "b" (untyped string constant) +// main/or_b3.gno:5:10: invalid operation: operator | not defined on "b" (untyped string constant) diff --git a/gnovm/tests/files/types/or_d0.gno b/gnovm/tests/files/types/or_d0.gno index 72c58b608a7..5fe02318a3f 100644 --- a/gnovm/tests/files/types/or_d0.gno +++ b/gnovm/tests/files/types/or_d0.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/or_d0.gno:6:10: operator | not defined on: BigdecKind +// main/or_d0.gno:6:10: operator | not defined on: BigdecKind // TypeCheckError: -// main/files/types/or_d0.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) +// main/or_d0.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/or_d4.gno b/gnovm/tests/files/types/or_d4.gno index 5efaf9a1571..3c3922d5621 100644 --- a/gnovm/tests/files/types/or_d4.gno +++ b/gnovm/tests/files/types/or_d4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/or_d4.gno:6:10: operator | not defined on: BigdecKind +// main/or_d4.gno:6:10: operator | not defined on: BigdecKind // TypeCheckError: -// main/files/types/or_d4.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) +// main/or_d4.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/or_e0.gno b/gnovm/tests/files/types/or_e0.gno index 2c40e2dd814..759144f1885 100644 --- a/gnovm/tests/files/types/or_e0.gno +++ b/gnovm/tests/files/types/or_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/files/types/or_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/or_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types Error1 and Error2) +// main/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_f0.gno b/gnovm/tests/files/types/or_f0.gno index 57ff4817b9a..946a651ab09 100644 --- a/gnovm/tests/files/types/or_f0.gno +++ b/gnovm/tests/files/types/or_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/or_f0.gno:19:10: operator | not defined on: InterfaceKind +// main/or_f0.gno:19:10: operator | not defined on: InterfaceKind // TypeCheckError: -// main/files/types/or_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} +// main/or_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/or_f1.gno b/gnovm/tests/files/types/or_f1.gno index 480265d8481..02a9b55f474 100644 --- a/gnovm/tests/files/types/or_f1.gno +++ b/gnovm/tests/files/types/or_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/files/types/or_f1.gno:19:10: operator | not defined on: InterfaceKind +// main/or_f1.gno:19:10: operator | not defined on: InterfaceKind // TypeCheckError: -// main/files/types/or_f1.gno:19:10: invalid operation: Error(0) | errCmp (mismatched types Error and error) +// main/or_f1.gno:19:10: invalid operation: Error(0) | errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/or_f2.gno b/gnovm/tests/files/types/or_f2.gno index dd9ef752bdc..62f330f848e 100644 --- a/gnovm/tests/files/types/or_f2.gno +++ b/gnovm/tests/files/types/or_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/files/types/or_f2.gno:27:10: operator | not defined on: InterfaceKind +// main/or_f2.gno:27:10: operator | not defined on: InterfaceKind // TypeCheckError: -// main/files/types/or_f2.gno:27:10: invalid operation: operator | not defined on e1 (variable of interface type E) +// main/or_f2.gno:27:10: invalid operation: operator | not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/overflow_a1.gno b/gnovm/tests/files/types/overflow_a1.gno index 787e8db2d98..de16e76f959 100644 --- a/gnovm/tests/files/types/overflow_a1.gno +++ b/gnovm/tests/files/types/overflow_a1.gno @@ -9,4 +9,4 @@ func main() { // cannot convert untyped bigdec to float64: strconv.ParseFloat: parsing "1E+1000": value out of range // TypeCheckError: -// main/files/types/overflow_a1.gno:5:10: cannot use Huge (untyped float constant 1e+1000) as float64 value in argument to built-in println (overflows) +// main/overflow_a1.gno:5:10: cannot use Huge (untyped float constant 1e+1000) as float64 value in argument to built-in println (overflows) diff --git a/gnovm/tests/files/types/rem_a0.gno b/gnovm/tests/files/types/rem_a0.gno index d57d5b99f7a..7f133a19086 100644 --- a/gnovm/tests/files/types/rem_a0.gno +++ b/gnovm/tests/files/types/rem_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/rem_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/rem_a0.gno:5:10: invalid operation: mismatched types int and int8 // TypeCheckError: -// main/files/types/rem_a0.gno:5:10: invalid operation: int(1) % int8(1) (mismatched types int and int8) +// main/rem_a0.gno:5:10: invalid operation: int(1) % int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/rem_a1.gno b/gnovm/tests/files/types/rem_a1.gno index a48e30b6269..cebd669d6ac 100644 --- a/gnovm/tests/files/types/rem_a1.gno +++ b/gnovm/tests/files/types/rem_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/files/types/rem_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/rem_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: -// main/files/types/rem_a1.gno:21:10: invalid operation: Error1(0) % Error2(0) (mismatched types Error1 and Error2) +// main/rem_a1.gno:21:10: invalid operation: Error1(0) % Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/rem_a2.gno b/gnovm/tests/files/types/rem_a2.gno index 41e00f1e7f2..ea1b730e968 100644 --- a/gnovm/tests/files/types/rem_a2.gno +++ b/gnovm/tests/files/types/rem_a2.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/rem_a2.gno:4:10: invalid operation: division by zero +// main/rem_a2.gno:4:10: invalid operation: division by zero // TypeCheckError: -// main/files/types/rem_a2.gno:4:14: invalid operation: division by zero +// main/rem_a2.gno:4:14: invalid operation: division by zero diff --git a/gnovm/tests/files/types/rem_f3.gno b/gnovm/tests/files/types/rem_f3.gno index 61590edbb78..afcc0455fb0 100644 --- a/gnovm/tests/files/types/rem_f3.gno +++ b/gnovm/tests/files/types/rem_f3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/rem_f3.gno:5:10: invalid operation: division by zero +// main/rem_f3.gno:5:10: invalid operation: division by zero // TypeCheckError: -// main/files/types/rem_f3.gno:5:14: invalid operation: division by zero +// main/rem_f3.gno:5:14: invalid operation: division by zero diff --git a/gnovm/tests/files/types/runtime_a0.gno b/gnovm/tests/files/types/runtime_a0.gno index b718066b374..7837471be01 100644 --- a/gnovm/tests/files/types/runtime_a0.gno +++ b/gnovm/tests/files/types/runtime_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/runtime_a0.gno:5:2: operator ++ not defined on: BoolKind +// main/runtime_a0.gno:5:2: operator ++ not defined on: BoolKind // TypeCheckError: -// main/files/types/runtime_a0.gno:5:2: invalid operation: m["foo"]++ (non-numeric type bool) +// main/runtime_a0.gno:5:2: invalid operation: m["foo"]++ (non-numeric type bool) diff --git a/gnovm/tests/files/types/runtime_a3.gno b/gnovm/tests/files/types/runtime_a3.gno index 8654871c4c1..d9c23dc03ab 100644 --- a/gnovm/tests/files/types/runtime_a3.gno +++ b/gnovm/tests/files/types/runtime_a3.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/runtime_a3.gno:8:2: operator ++ not defined on: InterfaceKind +// main/runtime_a3.gno:8:2: operator ++ not defined on: InterfaceKind // TypeCheckError: -// main/files/types/runtime_a3.gno:8:2: invalid operation: gen()++ (non-numeric type any) +// main/runtime_a3.gno:8:2: invalid operation: gen()++ (non-numeric type any) diff --git a/gnovm/tests/files/types/shift_a11.gno b/gnovm/tests/files/types/shift_a11.gno index 340af4f54c6..7d2e1572cf2 100644 --- a/gnovm/tests/files/types/shift_a11.gno +++ b/gnovm/tests/files/types/shift_a11.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_a11.gno:5:7: cannot convert (const ("hello" string)) to type uint +// main/shift_a11.gno:5:7: cannot convert (const ("hello" string)) to type uint // TypeCheckError: -// main/files/types/shift_a11.gno:5:12: cannot convert "hello" (untyped string constant) to type uint +// main/shift_a11.gno:5:12: cannot convert "hello" (untyped string constant) to type uint diff --git a/gnovm/tests/files/types/shift_a14.gno b/gnovm/tests/files/types/shift_a14.gno index 0ebef8c7fe4..a8aa69cf8a2 100644 --- a/gnovm/tests/files/types/shift_a14.gno +++ b/gnovm/tests/files/types/shift_a14.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_a14.gno:5:7: operator << not defined on: StringKind +// main/shift_a14.gno:5:7: operator << not defined on: StringKind // TypeCheckError: -// main/files/types/shift_a14.gno:5:7: invalid operation: shifted operand a (variable of type string) must be integer +// main/shift_a14.gno:5:7: invalid operation: shifted operand a (variable of type string) must be integer diff --git a/gnovm/tests/files/types/shift_a15.gno b/gnovm/tests/files/types/shift_a15.gno index 1a58dc5315b..0c09f586757 100644 --- a/gnovm/tests/files/types/shift_a15.gno +++ b/gnovm/tests/files/types/shift_a15.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_a15.gno:6:2: operator <<= not defined on: StringKind +// main/shift_a15.gno:6:2: operator <<= not defined on: StringKind // TypeCheckError: -// main/files/types/shift_a15.gno:6:2: invalid operation: shifted operand a (variable of type string) must be integer +// main/shift_a15.gno:6:2: invalid operation: shifted operand a (variable of type string) must be integer diff --git a/gnovm/tests/files/types/shift_a16.gno b/gnovm/tests/files/types/shift_a16.gno index 1a05561da5a..9768f46d00e 100644 --- a/gnovm/tests/files/types/shift_a16.gno +++ b/gnovm/tests/files/types/shift_a16.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_a16.gno:4:7: operator << not defined on: StringKind +// main/shift_a16.gno:4:7: operator << not defined on: StringKind // TypeCheckError: -// main/files/types/shift_a16.gno:4:7: invalid operation: shifted operand "hello" (untyped string constant) must be integer +// main/shift_a16.gno:4:7: invalid operation: shifted operand "hello" (untyped string constant) must be integer diff --git a/gnovm/tests/files/types/shift_a3.gno b/gnovm/tests/files/types/shift_a3.gno index 76a625d11d0..bafb206a416 100644 --- a/gnovm/tests/files/types/shift_a3.gno +++ b/gnovm/tests/files/types/shift_a3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_a3.gno:5:2: bigint overflows target kind +// main/shift_a3.gno:5:2: bigint overflows target kind // TypeCheckError: -// main/files/types/shift_a3.gno:5:10: cannot use 1 << 'a' (untyped int constant 158456325028528675187087900672) as int value in argument to built-in println (overflows) +// main/shift_a3.gno:5:10: cannot use 1 << 'a' (untyped int constant 158456325028528675187087900672) as int value in argument to built-in println (overflows) diff --git a/gnovm/tests/files/types/shift_a7.gno b/gnovm/tests/files/types/shift_a7.gno index ee7cb82f2fc..f8296e418a2 100644 --- a/gnovm/tests/files/types/shift_a7.gno +++ b/gnovm/tests/files/types/shift_a7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_a7.gno:5:10: cannot convert (const ("a" string)) to type uint +// main/shift_a7.gno:5:10: cannot convert (const ("a" string)) to type uint // TypeCheckError: -// main/files/types/shift_a7.gno:5:15: cannot convert "a" (untyped string constant) to type uint +// main/shift_a7.gno:5:15: cannot convert "a" (untyped string constant) to type uint diff --git a/gnovm/tests/files/types/shift_b6.gno b/gnovm/tests/files/types/shift_b6.gno index a537209a303..2799b973982 100644 --- a/gnovm/tests/files/types/shift_b6.gno +++ b/gnovm/tests/files/types/shift_b6.gno @@ -27,7 +27,7 @@ func main() { } // Error: -// main/files/types/shift_b6.gno:22:2: bigint does not implement main.R (missing method foo) +// main/shift_b6.gno:22:2: bigint does not implement main.R (missing method foo) // TypeCheckError: -// main/files/types/shift_b6.gno:22:6: cannot use 1 << x (value of type int) as R value in assignment: int does not implement R (missing method foo) +// main/shift_b6.gno:22:6: cannot use 1 << x (value of type int) as R value in assignment: int does not implement R (missing method foo) diff --git a/gnovm/tests/files/types/shift_b7.gno b/gnovm/tests/files/types/shift_b7.gno index 67d503503e4..81321a947a8 100644 --- a/gnovm/tests/files/types/shift_b7.gno +++ b/gnovm/tests/files/types/shift_b7.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/shift_b7.gno:7:7: operator << not defined on: Float32Kind +// main/shift_b7.gno:7:7: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_b7.gno:7:15: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_b7.gno:7:15: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c6.gno b/gnovm/tests/files/types/shift_c6.gno index 3103e449649..ec4ad707972 100644 --- a/gnovm/tests/files/types/shift_c6.gno +++ b/gnovm/tests/files/types/shift_c6.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/shift_c6.gno:8:2: operator << not defined on: Float32Kind +// main/shift_c6.gno:8:2: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_c6.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_c6.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c7.gno b/gnovm/tests/files/types/shift_c7.gno index 23f6d2016d7..35c0c146a63 100644 --- a/gnovm/tests/files/types/shift_c7.gno +++ b/gnovm/tests/files/types/shift_c7.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/shift_c7.gno:8:2: operator << not defined on: Float32Kind +// main/shift_c7.gno:8:2: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_c7.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_c7.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c8.gno b/gnovm/tests/files/types/shift_c8.gno index 43ef731714f..15b79bbf4b9 100644 --- a/gnovm/tests/files/types/shift_c8.gno +++ b/gnovm/tests/files/types/shift_c8.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/shift_c8.gno:8:2: cannot use int as float32 +// main/shift_c8.gno:8:2: cannot use int as float32 // TypeCheckError: -// main/files/types/shift_c8.gno:8:6: cannot use 1 << x + int(1) (value of type int) as float32 value in assignment +// main/shift_c8.gno:8:6: cannot use 1 << x + int(1) (value of type int) as float32 value in assignment diff --git a/gnovm/tests/files/types/shift_d12.gno b/gnovm/tests/files/types/shift_d12.gno index a905ff3f901..aa204b7c147 100644 --- a/gnovm/tests/files/types/shift_d12.gno +++ b/gnovm/tests/files/types/shift_d12.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/types/shift_d12.gno:12:2: operator >> not defined on: Float32Kind +// main/shift_d12.gno:12:2: operator >> not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d12.gno:12:12: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_d12.gno:12:12: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d13.gno b/gnovm/tests/files/types/shift_d13.gno index af4f7faa9d5..feca282535f 100644 --- a/gnovm/tests/files/types/shift_d13.gno +++ b/gnovm/tests/files/types/shift_d13.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/files/types/shift_d13.gno:13:2: cannot use int as float32 +// main/shift_d13.gno:13:2: cannot use int as float32 // TypeCheckError: -// main/files/types/shift_d13.gno:13:12: cannot use int(1) >> x (value of type int) as float32 value in argument to foo +// main/shift_d13.gno:13:12: cannot use int(1) >> x (value of type int) as float32 value in argument to foo diff --git a/gnovm/tests/files/types/shift_d27.gno b/gnovm/tests/files/types/shift_d27.gno index ae10c18a466..b3d978d04b5 100644 --- a/gnovm/tests/files/types/shift_d27.gno +++ b/gnovm/tests/files/types/shift_d27.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/shift_d27.gno:6:2: operator << not defined on: Float32Kind +// main/shift_d27.gno:6:2: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d27.gno:6:8: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_d27.gno:6:8: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d28.gno b/gnovm/tests/files/types/shift_d28.gno index 9aa72a55dcc..2f2161398e1 100644 --- a/gnovm/tests/files/types/shift_d28.gno +++ b/gnovm/tests/files/types/shift_d28.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/types/shift_d28.gno:6:2: operator << not defined on: Float32Kind +// main/shift_d28.gno:6:2: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d28.gno:6:10: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_d28.gno:6:10: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d32a.gno b/gnovm/tests/files/types/shift_d32a.gno index b76fbbf3b68..c86c784ab1a 100644 --- a/gnovm/tests/files/types/shift_d32a.gno +++ b/gnovm/tests/files/types/shift_d32a.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/shift_d32a.gno:7:7: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/shift_d32a.gno:7:7: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: -// main/files/types/shift_d32a.gno:7:16: invalid operation: shifted operand 1.2 (untyped float constant) must be integer +// main/shift_d32a.gno:7:16: invalid operation: shifted operand 1.2 (untyped float constant) must be integer diff --git a/gnovm/tests/files/types/shift_d34.gno b/gnovm/tests/files/types/shift_d34.gno index 1a7bae14ad6..bb1785e9cd6 100644 --- a/gnovm/tests/files/types/shift_d34.gno +++ b/gnovm/tests/files/types/shift_d34.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/shift_d34.gno:7:7: bigint underflows target kind +// main/shift_d34.gno:7:7: bigint underflows target kind // TypeCheckError: -// main/files/types/shift_d34.gno:7:14: -(1 << 2) (untyped int constant -4) overflows uint64 +// main/shift_d34.gno:7:14: -(1 << 2) (untyped int constant -4) overflows uint64 diff --git a/gnovm/tests/files/types/shift_d37.gno b/gnovm/tests/files/types/shift_d37.gno index 8eb9644d154..8f1e081ba06 100644 --- a/gnovm/tests/files/types/shift_d37.gno +++ b/gnovm/tests/files/types/shift_d37.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_d37.gno:5:10: operator << not defined on: nil +// main/shift_d37.gno:5:10: operator << not defined on: nil // TypeCheckError: -// main/files/types/shift_d37.gno:5:10: invalid operation: shifted operand nil must be integer +// main/shift_d37.gno:5:10: invalid operation: shifted operand nil must be integer diff --git a/gnovm/tests/files/types/shift_d38.gno b/gnovm/tests/files/types/shift_d38.gno index 1bde24123ba..fb5a8e7bed9 100644 --- a/gnovm/tests/files/types/shift_d38.gno +++ b/gnovm/tests/files/types/shift_d38.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/shift_d38.gno:4:10: cannot convert (const (undefined)) to type uint +// main/shift_d38.gno:4:10: cannot convert (const (undefined)) to type uint // TypeCheckError: -// main/files/types/shift_d38.gno:4:15: cannot convert nil to type uint +// main/shift_d38.gno:4:15: cannot convert nil to type uint diff --git a/gnovm/tests/files/types/shift_d4.gno b/gnovm/tests/files/types/shift_d4.gno index e50136ed07f..4a2dfbdc0d9 100644 --- a/gnovm/tests/files/types/shift_d4.gno +++ b/gnovm/tests/files/types/shift_d4.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_d4.gno:4:7: cannot convert BoolKind to Uint64Kind +// main/shift_d4.gno:4:7: cannot convert BoolKind to Uint64Kind // TypeCheckError: -// main/files/types/shift_d4.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type uint64 +// main/shift_d4.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type uint64 diff --git a/gnovm/tests/files/types/shift_d40.gno b/gnovm/tests/files/types/shift_d40.gno index 21650b6947d..5c870145e34 100644 --- a/gnovm/tests/files/types/shift_d40.gno +++ b/gnovm/tests/files/types/shift_d40.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d40.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d40.gno:5:7: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d40.gno:5:17: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_d40.gno:5:17: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d41.gno b/gnovm/tests/files/types/shift_d41.gno index 83504fc4821..6b093666018 100644 --- a/gnovm/tests/files/types/shift_d41.gno +++ b/gnovm/tests/files/types/shift_d41.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d41.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d41.gno:5:7: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d41.gno:5:31: invalid operation: shifted operand 1 (type float32) must be integer +// main/shift_d41.gno:5:31: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d44.gno b/gnovm/tests/files/types/shift_d44.gno index 3d79d257702..1136a9269dd 100644 --- a/gnovm/tests/files/types/shift_d44.gno +++ b/gnovm/tests/files/types/shift_d44.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d44.gno:6:2: operator ++ not defined on: BoolKind +// main/shift_d44.gno:6:2: operator ++ not defined on: BoolKind // TypeCheckError: -// main/files/types/shift_d44.gno:6:2: invalid operation: (a == b)++ (non-numeric type untyped bool) +// main/shift_d44.gno:6:2: invalid operation: (a == b)++ (non-numeric type untyped bool) diff --git a/gnovm/tests/files/types/shift_d4a.gno b/gnovm/tests/files/types/shift_d4a.gno index 7d4b0a8a3b9..b3a67e6a4fb 100644 --- a/gnovm/tests/files/types/shift_d4a.gno +++ b/gnovm/tests/files/types/shift_d4a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_d4a.gno:4:7: cannot convert BoolKind to StringKind +// main/shift_d4a.gno:4:7: cannot convert BoolKind to StringKind // TypeCheckError: -// main/files/types/shift_d4a.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type string +// main/shift_d4a.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type string diff --git a/gnovm/tests/files/types/shift_d5.gno b/gnovm/tests/files/types/shift_d5.gno index 3718627dfaa..55732155c24 100644 --- a/gnovm/tests/files/types/shift_d5.gno +++ b/gnovm/tests/files/types/shift_d5.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d5.gno:5:2: operator << not defined on: Float64Kind +// main/shift_d5.gno:5:2: operator << not defined on: Float64Kind // TypeCheckError: -// main/files/types/shift_d5.gno:5:7: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_d5.gno:5:7: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_d50.gno b/gnovm/tests/files/types/shift_d50.gno index 84cbcc4b09d..4a0875202e9 100644 --- a/gnovm/tests/files/types/shift_d50.gno +++ b/gnovm/tests/files/types/shift_d50.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/shift_d50.gno:7:7: bigint underflows target kind +// main/shift_d50.gno:7:7: bigint underflows target kind // TypeCheckError: -// main/files/types/shift_d50.gno:7:14: -(1.0 << 2) (untyped int constant -4) overflows uint64 +// main/shift_d50.gno:7:14: -(1.0 << 2) (untyped int constant -4) overflows uint64 diff --git a/gnovm/tests/files/types/shift_d51.gno b/gnovm/tests/files/types/shift_d51.gno index fcfddb6b1eb..c144eb1da36 100644 --- a/gnovm/tests/files/types/shift_d51.gno +++ b/gnovm/tests/files/types/shift_d51.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d51.gno:5:2: operator <<= not defined on: Float64Kind +// main/shift_d51.gno:5:2: operator <<= not defined on: Float64Kind // TypeCheckError: -// main/files/types/shift_d51.gno:5:2: invalid operation: shifted operand a (variable of type float64) must be integer +// main/shift_d51.gno:5:2: invalid operation: shifted operand a (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_d54.gno b/gnovm/tests/files/types/shift_d54.gno index 696dd10c8e6..66fdb1963f4 100644 --- a/gnovm/tests/files/types/shift_d54.gno +++ b/gnovm/tests/files/types/shift_d54.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/types/shift_d54.gno:8:7: invalid operation: mismatched types int32 and int +// main/shift_d54.gno:8:7: invalid operation: mismatched types int32 and int // TypeCheckError: -// main/files/types/shift_d54.gno:8:7: invalid operation: b + a << 2 (mismatched types int32 and int) +// main/shift_d54.gno:8:7: invalid operation: b + a << 2 (mismatched types int32 and int) diff --git a/gnovm/tests/files/types/shift_d56.gno b/gnovm/tests/files/types/shift_d56.gno index b338c874058..08224bbcdbc 100644 --- a/gnovm/tests/files/types/shift_d56.gno +++ b/gnovm/tests/files/types/shift_d56.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/files/types/shift_d56.gno:6:2: cannot use int as int64 +// main/shift_d56.gno:6:2: cannot use int as int64 // TypeCheckError: -// main/files/types/shift_d56.gno:6:9: cannot use 1 << 4 + int(1) (constant 17 of type int) as int64 value in return statement +// main/shift_d56.gno:6:9: cannot use 1 << 4 + int(1) (constant 17 of type int) as int64 value in return statement diff --git a/gnovm/tests/files/types/shift_d5b.gno b/gnovm/tests/files/types/shift_d5b.gno index dce39a77c5e..c3d8dcd7370 100644 --- a/gnovm/tests/files/types/shift_d5b.gno +++ b/gnovm/tests/files/types/shift_d5b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_d5b.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d5b.gno:5:7: operator << not defined on: Float32Kind // TypeCheckError: -// main/files/types/shift_d5b.gno:5:15: invalid operation: shifted operand 1.0 (type float32) must be integer +// main/shift_d5b.gno:5:15: invalid operation: shifted operand 1.0 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_e0.gno b/gnovm/tests/files/types/shift_e0.gno index 76c01a25526..71b0bc6bd35 100644 --- a/gnovm/tests/files/types/shift_e0.gno +++ b/gnovm/tests/files/types/shift_e0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/shift_e0.gno:4:10: invalid operation: negative shift count: (const (-1 bigint)) +// main/shift_e0.gno:4:10: invalid operation: negative shift count: (const (-1 bigint)) // TypeCheckError: -// main/files/types/shift_e0.gno:4:15: invalid operation: negative shift count -1 (untyped int constant) +// main/shift_e0.gno:4:15: invalid operation: negative shift count -1 (untyped int constant) diff --git a/gnovm/tests/files/types/shift_e1.gno b/gnovm/tests/files/types/shift_e1.gno index 7e4ca22be13..7246dd5b9de 100644 --- a/gnovm/tests/files/types/shift_e1.gno +++ b/gnovm/tests/files/types/shift_e1.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/shift_e1.gno:4:10: invalid operation: invalid shift count: (const (2.5848584 float32)) +// main/shift_e1.gno:4:10: invalid operation: invalid shift count: (const (2.5848584 float32)) // TypeCheckError: -// main/files/types/shift_e1.gno:4:17: invalid operation: invalid shift count float32(2.58485848) (constant 2.58486 of type float32) +// main/shift_e1.gno:4:17: invalid operation: invalid shift count float32(2.58485848) (constant 2.58486 of type float32) diff --git a/gnovm/tests/files/types/shift_e2.gno b/gnovm/tests/files/types/shift_e2.gno index c409a0527de..da7b6ef7d59 100644 --- a/gnovm/tests/files/types/shift_e2.gno +++ b/gnovm/tests/files/types/shift_e2.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/shift_e2.gno:4:10: invalid operation: invalid shift count: (const (1.25 bigdec)) +// main/shift_e2.gno:4:10: invalid operation: invalid shift count: (const (1.25 bigdec)) // TypeCheckError: -// main/files/types/shift_e2.gno:4:15: 1.25 (untyped float constant) truncated to uint +// main/shift_e2.gno:4:15: 1.25 (untyped float constant) truncated to uint diff --git a/gnovm/tests/files/types/shift_e3.gno b/gnovm/tests/files/types/shift_e3.gno index 4db44bda080..1d6048bc9c3 100644 --- a/gnovm/tests/files/types/shift_e3.gno +++ b/gnovm/tests/files/types/shift_e3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_e3.gno:5:10: invalid operation: invalid shift count: x +// main/shift_e3.gno:5:10: invalid operation: invalid shift count: x // TypeCheckError: -// main/files/types/shift_e3.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer +// main/shift_e3.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e4.gno b/gnovm/tests/files/types/shift_e4.gno index 716f4802d9c..05c20a6ed23 100644 --- a/gnovm/tests/files/types/shift_e4.gno +++ b/gnovm/tests/files/types/shift_e4.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_e4.gno:5:10: invalid operation: invalid shift count: x +// main/shift_e4.gno:5:10: invalid operation: invalid shift count: x // TypeCheckError: -// main/files/types/shift_e4.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer +// main/shift_e4.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e7.gno b/gnovm/tests/files/types/shift_e7.gno index 40bd1a1b12b..360e6c8fd9e 100644 --- a/gnovm/tests/files/types/shift_e7.gno +++ b/gnovm/tests/files/types/shift_e7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_e7.gno:5:2: invalid operation: negative shift count: (-1 bigint) +// main/shift_e7.gno:5:2: invalid operation: negative shift count: (-1 bigint) // TypeCheckError: -// main/files/types/shift_e7.gno:5:8: invalid operation: negative shift count -1 (untyped int constant) +// main/shift_e7.gno:5:8: invalid operation: negative shift count -1 (untyped int constant) diff --git a/gnovm/tests/files/types/shift_e7a.gno b/gnovm/tests/files/types/shift_e7a.gno index a4ee105e6a9..8cdd455f8fc 100644 --- a/gnovm/tests/files/types/shift_e7a.gno +++ b/gnovm/tests/files/types/shift_e7a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_e7a.gno:5:10: invalid operation: invalid shift count: a +// main/shift_e7a.gno:5:10: invalid operation: invalid shift count: a // TypeCheckError: -// main/files/types/shift_e7a.gno:5:15: invalid operation: shift count a (variable of type float64) must be integer +// main/shift_e7a.gno:5:15: invalid operation: shift count a (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e7b.gno b/gnovm/tests/files/types/shift_e7b.gno index eb478b4ea01..6fed70c69f9 100644 --- a/gnovm/tests/files/types/shift_e7b.gno +++ b/gnovm/tests/files/types/shift_e7b.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/types/shift_e7b.gno:4:10: invalid operation: invalid shift count: (const (-1 float64)) +// main/shift_e7b.gno:4:10: invalid operation: invalid shift count: (const (-1 float64)) // TypeCheckError: -// main/files/types/shift_e7b.gno:4:15: invalid operation: negative shift count float64(-1) (constant -1 of type float64) +// main/shift_e7b.gno:4:15: invalid operation: negative shift count float64(-1) (constant -1 of type float64) diff --git a/gnovm/tests/files/types/shift_e8.gno b/gnovm/tests/files/types/shift_e8.gno index df6ad257419..859613a1d54 100644 --- a/gnovm/tests/files/types/shift_e8.gno +++ b/gnovm/tests/files/types/shift_e8.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/types/shift_e8.gno:5:2: invalid operation: invalid shift count: (const (1.25 bigdec)) +// main/shift_e8.gno:5:2: invalid operation: invalid shift count: (const (1.25 bigdec)) // TypeCheckError: -// main/files/types/shift_e8.gno:5:8: 1.25 (untyped float constant) truncated to uint +// main/shift_e8.gno:5:8: 1.25 (untyped float constant) truncated to uint diff --git a/gnovm/tests/files/types/shift_f1b.gno b/gnovm/tests/files/types/shift_f1b.gno index 57f20483b4d..2ec54e4dc94 100644 --- a/gnovm/tests/files/types/shift_f1b.gno +++ b/gnovm/tests/files/types/shift_f1b.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/shift_f1b.gno:7:2: operator << not defined on: BigdecKind +// main/shift_f1b.gno:7:2: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f1b.gno:7:7: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f1b.gno:7:7: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2.gno b/gnovm/tests/files/types/shift_f2.gno index 203fdc54fc8..a1b4955f996 100644 --- a/gnovm/tests/files/types/shift_f2.gno +++ b/gnovm/tests/files/types/shift_f2.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f2.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f2.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer +// main/shift_f2.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2a.gno b/gnovm/tests/files/types/shift_f2a.gno index 719539582a1..93f2e5cc953 100644 --- a/gnovm/tests/files/types/shift_f2a.gno +++ b/gnovm/tests/files/types/shift_f2a.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f2a.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2a.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f2a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f2a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2b.gno b/gnovm/tests/files/types/shift_f2b.gno index e0824f17813..a6b33f098c1 100644 --- a/gnovm/tests/files/types/shift_f2b.gno +++ b/gnovm/tests/files/types/shift_f2b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f2b.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2b.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f2b.gno:5:18: invalid operation: shifted operand 1 (type float64) must be integer +// main/shift_f2b.gno:5:18: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2c.gno b/gnovm/tests/files/types/shift_f2c.gno index 20e918d75da..3566824c613 100644 --- a/gnovm/tests/files/types/shift_f2c.gno +++ b/gnovm/tests/files/types/shift_f2c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f2c.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2c.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f2c.gno:5:16: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f2c.gno:5:16: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2d.gno b/gnovm/tests/files/types/shift_f2d.gno index 0fa94fca480..a5721b3ce64 100644 --- a/gnovm/tests/files/types/shift_f2d.gno +++ b/gnovm/tests/files/types/shift_f2d.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f2d.gno:5:11: incompatible types in binary expression: bigint NEQ bigdec +// main/shift_f2d.gno:5:11: incompatible types in binary expression: bigint NEQ bigdec // TypeCheckError: -// main/files/types/shift_f2d.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer; main/files/types/shift_f2d.gno:5:19: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f2d.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer; main/shift_f2d.gno:5:19: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3.gno b/gnovm/tests/files/types/shift_f3.gno index eb5651237d4..ff949765250 100644 --- a/gnovm/tests/files/types/shift_f3.gno +++ b/gnovm/tests/files/types/shift_f3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f3.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f3.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer +// main/shift_f3.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3a.gno b/gnovm/tests/files/types/shift_f3a.gno index 78b2a5d5983..5fd159536dc 100644 --- a/gnovm/tests/files/types/shift_f3a.gno +++ b/gnovm/tests/files/types/shift_f3a.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f3a.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3a.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f3a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f3a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3b.gno b/gnovm/tests/files/types/shift_f3b.gno index c967e4eff0e..1a914c8ab75 100644 --- a/gnovm/tests/files/types/shift_f3b.gno +++ b/gnovm/tests/files/types/shift_f3b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f3b.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3b.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f3b.gno:5:17: invalid operation: shifted operand 1 (type float64) must be integer +// main/shift_f3b.gno:5:17: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3c.gno b/gnovm/tests/files/types/shift_f3c.gno index e60b0a2bc25..cce2059d28e 100644 --- a/gnovm/tests/files/types/shift_f3c.gno +++ b/gnovm/tests/files/types/shift_f3c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/types/shift_f3c.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3c.gno:5:6: operator << not defined on: BigdecKind // TypeCheckError: -// main/files/types/shift_f3c.gno:5:15: invalid operation: shifted operand 1.0 (type float64) must be integer +// main/shift_f3c.gno:5:15: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/typed_nil_a.gno b/gnovm/tests/files/types/typed_nil_a.gno index 14a580dcb19..494b2741480 100644 --- a/gnovm/tests/files/types/typed_nil_a.gno +++ b/gnovm/tests/files/types/typed_nil_a.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/files/types/typed_nil_a.gno:10:5: cannot convert (const (undefined)) to IntKind +// main/typed_nil_a.gno:10:5: cannot convert (const (undefined)) to IntKind // TypeCheckError: -// main/files/types/typed_nil_a.gno:10:13: cannot convert nil to type integer +// main/typed_nil_a.gno:10:13: cannot convert nil to type integer diff --git a/gnovm/tests/files/types/unary_a0c.gno b/gnovm/tests/files/types/unary_a0c.gno index 8f1a2a3bd79..9edb1a51de5 100644 --- a/gnovm/tests/files/types/unary_a0c.gno +++ b/gnovm/tests/files/types/unary_a0c.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/unary_a0c.gno:7:7: operator + not defined on: StringKind +// main/unary_a0c.gno:7:7: operator + not defined on: StringKind // TypeCheckError: -// main/files/types/unary_a0c.gno:7:8: invalid operation: operator + not defined on x (variable of type string) +// main/unary_a0c.gno:7:8: invalid operation: operator + not defined on x (variable of type string) diff --git a/gnovm/tests/files/types/unary_a2a.gno b/gnovm/tests/files/types/unary_a2a.gno index cb89774524b..adc45057a69 100644 --- a/gnovm/tests/files/types/unary_a2a.gno +++ b/gnovm/tests/files/types/unary_a2a.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/files/types/unary_a2a.gno:7:7: operator ! not defined on: IntKind +// main/unary_a2a.gno:7:7: operator ! not defined on: IntKind // TypeCheckError: -// main/files/types/unary_a2a.gno:7:8: invalid operation: operator ! not defined on a (variable of type int) +// main/unary_a2a.gno:7:8: invalid operation: operator ! not defined on a (variable of type int) diff --git a/gnovm/tests/files/types/unary_a6.gno b/gnovm/tests/files/types/unary_a6.gno index cbbff69bd78..8c1c608e9b6 100644 --- a/gnovm/tests/files/types/unary_a6.gno +++ b/gnovm/tests/files/types/unary_a6.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/types/unary_a6.gno:7:7: operator ^ not defined on: Float64Kind +// main/unary_a6.gno:7:7: operator ^ not defined on: Float64Kind // TypeCheckError: -// main/files/types/unary_a6.gno:7:8: invalid operation: operator ^ not defined on x (variable of type float64) +// main/unary_a6.gno:7:8: invalid operation: operator ^ not defined on x (variable of type float64) diff --git a/gnovm/tests/files/var18.gno b/gnovm/tests/files/var18.gno index 8ecf3a6d1f7..75f5143b742 100644 --- a/gnovm/tests/files/var18.gno +++ b/gnovm/tests/files/var18.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/var18.gno:4:6: missing init expr for c +// main/var18.gno:4:6: missing init expr for c // TypeCheckError: -// main/files/var18.gno:4:12: missing init expr for c; main/files/var18.gno:4:6: declared and not used: a; main/files/var18.gno:4:9: declared and not used: b; main/files/var18.gno:4:12: declared and not used: c +// main/var18.gno:4:12: missing init expr for c; main/var18.gno:4:6: declared and not used: a; main/var18.gno:4:9: declared and not used: b; main/var18.gno:4:12: declared and not used: c diff --git a/gnovm/tests/files/var19.gno b/gnovm/tests/files/var19.gno index 7beb76863eb..6d632326b56 100644 --- a/gnovm/tests/files/var19.gno +++ b/gnovm/tests/files/var19.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/var19.gno:4:6: missing init expr for c +// main/var19.gno:4:6: missing init expr for c // TypeCheckError: -// main/files/var19.gno:4:12: missing init expr for c; main/files/var19.gno:4:19: undefined: a +// main/var19.gno:4:12: missing init expr for c; main/var19.gno:4:19: undefined: a diff --git a/gnovm/tests/files/var20.gno b/gnovm/tests/files/var20.gno index 4886a6b1932..ea9743889dd 100644 --- a/gnovm/tests/files/var20.gno +++ b/gnovm/tests/files/var20.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/files/var20.gno:8:6: assignment mismatch: 3 variable(s) but r() returns 1 value(s) +// main/var20.gno:8:6: assignment mismatch: 3 variable(s) but r() returns 1 value(s) // TypeCheckError: -// main/files/var20.gno:8:16: assignment mismatch: 3 variables but r returns 1 value; main/files/var20.gno:8:6: declared and not used: a; main/files/var20.gno:8:9: declared and not used: b; main/files/var20.gno:8:12: declared and not used: c +// main/var20.gno:8:16: assignment mismatch: 3 variables but r returns 1 value; main/var20.gno:8:6: declared and not used: a; main/var20.gno:8:9: declared and not used: b; main/var20.gno:8:12: declared and not used: c diff --git a/gnovm/tests/files/var21.gno b/gnovm/tests/files/var21.gno index 19a29bb439f..cd07ed99020 100644 --- a/gnovm/tests/files/var21.gno +++ b/gnovm/tests/files/var21.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/var21.gno:8:6: multiple-value foo (value of type [int bool]) in single-value context +// main/var21.gno:8:6: multiple-value foo (value of type [int bool]) in single-value context // TypeCheckError: -// main/files/var21.gno:8:16: multiple-value foo() (value of type (int, bool)) in single-value context +// main/var21.gno:8:16: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/var22.gno b/gnovm/tests/files/var22.gno index c78d5abeb4c..86923221c0e 100644 --- a/gnovm/tests/files/var22.gno +++ b/gnovm/tests/files/var22.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/var22.gno:8:6: missing init expr for c +// main/var22.gno:8:6: missing init expr for c // TypeCheckError: -// main/files/var22.gno:8:12: missing init expr for c; main/files/var22.gno:8:19: multiple-value foo() (value of type (int, bool)) in single-value context +// main/var22.gno:8:12: missing init expr for c; main/var22.gno:8:19: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/var22b.gno b/gnovm/tests/files/var22b.gno index 4a90aecf2fa..aeea596973b 100644 --- a/gnovm/tests/files/var22b.gno +++ b/gnovm/tests/files/var22b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/files/var22b.gno:8:6: extra init expr foo() +// main/var22b.gno:8:6: extra init expr foo() // TypeCheckError: -// main/files/var22b.gno:8:25: extra init expr foo() +// main/var22b.gno:8:25: extra init expr foo() diff --git a/gnovm/tests/files/var22c.gno b/gnovm/tests/files/var22c.gno index cc296246d99..ff31963e8d7 100644 --- a/gnovm/tests/files/var22c.gno +++ b/gnovm/tests/files/var22c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/files/var22c.gno:10:6: missing init expr for z +// main/var22c.gno:10:6: missing init expr for z // TypeCheckError: -// main/files/var22c.gno:10:12: missing init expr for z; main/files/var22c.gno:10:19: multiple-value f() (value of type (a int, b int)) in single-value context +// main/var22c.gno:10:12: missing init expr for z; main/var22c.gno:10:19: multiple-value f() (value of type (a int, b int)) in single-value context diff --git a/gnovm/tests/files/var23.gno b/gnovm/tests/files/var23.gno index fc7b0fd05b4..02c2a9be9ef 100644 --- a/gnovm/tests/files/var23.gno +++ b/gnovm/tests/files/var23.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/var23.gno:3:5: assignment mismatch: 3 variable(s) but 2 value(s) +// main/var23.gno:3:5: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: -// main/files/var23.gno:3:11: missing init expr for c +// main/var23.gno:3:11: missing init expr for c diff --git a/gnovm/tests/files/var24.gno b/gnovm/tests/files/var24.gno index c5112d6bf97..92c2c677323 100644 --- a/gnovm/tests/files/var24.gno +++ b/gnovm/tests/files/var24.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/var24.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) +// main/var24.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: -// main/files/var24.gno:5:16: assignment mismatch: 3 variables but 1 value; main/files/var24.gno:5:6: declared and not used: a; main/files/var24.gno:5:9: declared and not used: b; main/files/var24.gno:5:12: declared and not used: c +// main/var24.gno:5:16: assignment mismatch: 3 variables but 1 value; main/var24.gno:5:6: declared and not used: a; main/var24.gno:5:9: declared and not used: b; main/var24.gno:5:12: declared and not used: c diff --git a/gnovm/tests/files/var25.gno b/gnovm/tests/files/var25.gno index dd0e3bdf360..8bb56589a51 100644 --- a/gnovm/tests/files/var25.gno +++ b/gnovm/tests/files/var25.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/files/var25.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) +// main/var25.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: -// main/files/var25.gno:5:16: assignment mismatch: 3 variables but 1 value; main/files/var25.gno:5:6: declared and not used: a; main/files/var25.gno:5:9: declared and not used: b; main/files/var25.gno:5:12: declared and not used: c +// main/var25.gno:5:16: assignment mismatch: 3 variables but 1 value; main/var25.gno:5:6: declared and not used: a; main/var25.gno:5:9: declared and not used: b; main/var25.gno:5:12: declared and not used: c diff --git a/gnovm/tests/files/var26.gno b/gnovm/tests/files/var26.gno index 2cc7fed3e85..fcbeff3027d 100644 --- a/gnovm/tests/files/var26.gno +++ b/gnovm/tests/files/var26.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/var26.gno:6:6: extra init expr 3 +// main/var26.gno:6:6: extra init expr 3 // TypeCheckError: -// main/files/var26.gno:6:19: extra init expr 3 +// main/var26.gno:6:19: extra init expr 3 diff --git a/gnovm/tests/files/var27.gno b/gnovm/tests/files/var27.gno index 05f8e56da22..2f8d65d330b 100644 --- a/gnovm/tests/files/var27.gno +++ b/gnovm/tests/files/var27.gno @@ -80,4 +80,4 @@ var other1 = func() { var something1 = "a string" // TypeCheckError: -// main/files/var27.gno:8:2: declared and not used: a +// main/var27.gno:8:2: declared and not used: a diff --git a/gnovm/tests/files/var31.gno b/gnovm/tests/files/var31.gno index 001e34f88cf..db5f1c0aa46 100644 --- a/gnovm/tests/files/var31.gno +++ b/gnovm/tests/files/var31.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/var31.gno:4:6: struct{} (type) is not an expression +// main/var31.gno:4:6: struct{} (type) is not an expression // TypeCheckError: -// main/files/var31.gno:4:10: struct{} (type) is not an expression; main/files/var31.gno:4:6: declared and not used: t +// main/var31.gno:4:10: struct{} (type) is not an expression; main/var31.gno:4:6: declared and not used: t diff --git a/gnovm/tests/files/var32.gno b/gnovm/tests/files/var32.gno index ec7abb92d95..196be88d48a 100644 --- a/gnovm/tests/files/var32.gno +++ b/gnovm/tests/files/var32.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/var32.gno:4:6: use of untyped nil in variable declaration +// main/var32.gno:4:6: use of untyped nil in variable declaration // TypeCheckError: -// main/files/var32.gno:4:10: use of untyped nil in variable declaration; main/files/var32.gno:4:6: declared and not used: t +// main/var32.gno:4:10: use of untyped nil in variable declaration; main/var32.gno:4:6: declared and not used: t diff --git a/gnovm/tests/files/var33.gno b/gnovm/tests/files/var33.gno index 4fb1ac5f45f..5198b817d97 100644 --- a/gnovm/tests/files/var33.gno +++ b/gnovm/tests/files/var33.gno @@ -9,4 +9,4 @@ func main() { // pass // TypeCheckError: -// main/files/var33.gno:4:6: declared and not used: t +// main/var33.gno:4:6: declared and not used: t diff --git a/gnovm/tests/files/var34.gno b/gnovm/tests/files/var34.gno index e6e3a35870d..1bd82630473 100644 --- a/gnovm/tests/files/var34.gno +++ b/gnovm/tests/files/var34.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/var34.gno:6:6: f (no value) used as value +// main/var34.gno:6:6: f (no value) used as value // TypeCheckError: -// main/files/var34.gno:6:10: f() (no value) used as value; main/files/var34.gno:6:6: declared and not used: t +// main/var34.gno:6:10: f() (no value) used as value; main/var34.gno:6:6: declared and not used: t diff --git a/gnovm/tests/files/var34b.gno b/gnovm/tests/files/var34b.gno index d3175fa531f..cfe47823865 100644 --- a/gnovm/tests/files/var34b.gno +++ b/gnovm/tests/files/var34b.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/files/var34b.gno:7:2: f (no value) used as value +// main/var34b.gno:7:2: f (no value) used as value // TypeCheckError: -// main/files/var34b.gno:7:6: f() (no value) used as value; main/files/var34b.gno:6:6: declared and not used: a +// main/var34b.gno:7:6: f() (no value) used as value; main/var34b.gno:6:6: declared and not used: a diff --git a/gnovm/tests/files/var34c.gno b/gnovm/tests/files/var34c.gno index e1e6376d278..5491d74a6a4 100644 --- a/gnovm/tests/files/var34c.gno +++ b/gnovm/tests/files/var34c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/files/var34c.gno:6:6: f (no value) used as value +// main/var34c.gno:6:6: f (no value) used as value // TypeCheckError: -// main/files/var34c.gno:6:17: f() (no value) used as value; main/files/var34c.gno:6:6: declared and not used: a; main/files/var34c.gno:6:9: declared and not used: b +// main/var34c.gno:6:17: f() (no value) used as value; main/var34c.gno:6:6: declared and not used: a; main/var34c.gno:6:9: declared and not used: b diff --git a/gnovm/tests/files/var35.gno b/gnovm/tests/files/var35.gno index 5f8a1fbfa85..c91057dfe24 100644 --- a/gnovm/tests/files/var35.gno +++ b/gnovm/tests/files/var35.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/files/var35.gno:4:6: cannot use nil as int value in variable declaration +// main/var35.gno:4:6: cannot use nil as int value in variable declaration // TypeCheckError: -// main/files/var35.gno:4:14: cannot use nil as int value in variable declaration; main/files/var35.gno:4:6: declared and not used: i +// main/var35.gno:4:14: cannot use nil as int value in variable declaration; main/var35.gno:4:6: declared and not used: i diff --git a/gnovm/tests/files/zrealm_crossrealm22.gno b/gnovm/tests/files/zrealm_crossrealm22.gno index 3c1789b9ed1..9f8e9da3bb8 100644 --- a/gnovm/tests/files/zrealm_crossrealm22.gno +++ b/gnovm/tests/files/zrealm_crossrealm22.gno @@ -97,10 +97,19 @@ func main() { // "@type": "/gno.RefNode", // "BlockNode": null, // "Location": { -// "Column": "35", -// "File": "files/zrealm_crossrealm22.gno", -// "Line": "13", -// "PkgPath": "gno.land/r/crossrealm_test" +// "File": "zrealm_crossrealm22.gno", +// "PkgPath": "gno.land/r/crossrealm_test", +// "Span": { +// "End": { +// "Column": "71", +// "Line": "13" +// }, +// "Num": "0", +// "Pos": { +// "Column": "35", +// "Line": "13" +// } +// } // } // }, // "Type": { @@ -136,7 +145,7 @@ func main() { // + }, // + "V": { // + "@type": "/gno.RefValue", -// + "Hash": "496beec28378b765d658286561b08be89e32efee", +// + "Hash": "95bd5e4ce205cb541fd5e0ef755457f33b725dc7", // + "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:36" // } // } @@ -203,7 +212,7 @@ func main() { // }, // "V": { // "@type": "/gno.RefValue", -// - "Hash": "496beec28378b765d658286561b08be89e32efee", +// - "Hash": "95bd5e4ce205cb541fd5e0ef755457f33b725dc7", // - "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:36" // + "Escaped": true, // + "ObjectID": "0edc46caf30c00efd87b6c272673239eafbd051e:7" @@ -279,10 +288,19 @@ func main() { // "@type": "/gno.RefNode", // "BlockNode": null, // "Location": { -// "Column": "62", // "File": "crossrealm.gno", -// "Line": "26", -// "PkgPath": "gno.land/r/demo/tests/crossrealm_b" +// "PkgPath": "gno.land/r/demo/tests/crossrealm_b", +// "Span": { +// "End": { +// "Column": "102", +// "Line": "26" +// }, +// "Num": "0", +// "Pos": { +// "Column": "62", +// "Line": "26" +// } +// } // } // }, // "Type": { @@ -308,7 +326,7 @@ func main() { // "@type": "/gno.RefValue", // - "Escaped": true, // - "ObjectID": "0edc46caf30c00efd87b6c272673239eafbd051e:7" -// + "Hash": "6a8bf31929a4f73151f3b404c376f279bacd9c81", +// + "Hash": "a43fc472719083cebcd120f2d1232bd77c87801f", // + "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:38" // } // } diff --git a/gnovm/tests/files/zrealm_crossrealm28.gno b/gnovm/tests/files/zrealm_crossrealm28.gno index 17ee77d4059..17cdbe46a64 100644 --- a/gnovm/tests/files/zrealm_crossrealm28.gno +++ b/gnovm/tests/files/zrealm_crossrealm28.gno @@ -52,7 +52,7 @@ func main() { // - }, // - "V": { // - "@type": "/gno.RefValue", -// - "Hash": "5b8e03f7f8b6fe2399fb8f4a27dd5a1a49518df8", +// - "Hash": "47596878835b82fc5bcd8469e6d3f9b90e545e45", // - "ObjectID": "0edc46caf30c00efd87b6c272673239eafbd051e:16" // + "@type": "/gno.PrimitiveType", // + "value": "32" diff --git a/gnovm/tests/files/zrealm_natbind0.gno b/gnovm/tests/files/zrealm_natbind0.gno index e12f8014119..45b8410e609 100644 --- a/gnovm/tests/files/zrealm_natbind0.gno +++ b/gnovm/tests/files/zrealm_natbind0.gno @@ -44,16 +44,16 @@ func main() { // "V": { // "@type": "/gno.RefValue", // "Escaped": true, -// - "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:36" -// + "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:33" +// - "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:39" +// + "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:36" // } // } // } -// u[a7f5397443359ea76c50be82c77f1f893a060925:33]= +// u[a7f5397443359ea76c50be82c77f1f893a060925:36]= // @@ -8,9 +8,10 @@ // "NativePkg": "std", // "ObjectInfo": { -// "ID": "a7f5397443359ea76c50be82c77f1f893a060925:33", +// "ID": "a7f5397443359ea76c50be82c77f1f893a060925:36", // - "ModTime": "0", // + "IsEscaped": true, // + "ModTime": "6", @@ -63,7 +63,7 @@ func main() { // }, // "Parent": { // "@type": "/gno.RefValue", -// u[a7f5397443359ea76c50be82c77f1f893a060925:36]= +// u[a7f5397443359ea76c50be82c77f1f893a060925:39]= // @@ -11,7 +11,7 @@ // "IsEscaped": true, // "ModTime": "6", diff --git a/gnovm/tests/files/zrealm_panic.gno b/gnovm/tests/files/zrealm_panic.gno index 12078b33a80..f94f9ade1f6 100644 --- a/gnovm/tests/files/zrealm_panic.gno +++ b/gnovm/tests/files/zrealm_panic.gno @@ -20,6 +20,6 @@ func main() { // Stacktrace: // panic: panic // ms.Panic() -// gno.land/r/test/files/zrealm_panic.gno:7 +// gno.land/r/test/zrealm_panic.gno:7 // main() -// gno.land/r/test/files/zrealm_panic.gno:14 +// gno.land/r/test/zrealm_panic.gno:14 diff --git a/gnovm/tests/integ/init/gno.mod b/gnovm/tests/integ/init/gno.mod index 28c7e51b750..71278f21b8f 100644 --- a/gnovm/tests/integ/init/gno.mod +++ b/gnovm/tests/integ/init/gno.mod @@ -1 +1,3 @@ module gno.land/r/demo/init + +gno 0.9 From cae70df303fa885579ef085ffd5e1738e53b7905 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 12 May 2025 20:17:41 -0700 Subject: [PATCH 17/83] separate _test and filetest files --- ..._transpile.md => pr4264_lint_transpile.md} | 0 gnovm/cmd/gno/test.go | 2 +- gnovm/cmd/gno/tool_lint.go | 15 +++--- gnovm/pkg/gnolang/gotypecheck.go | 52 +++++++++++++------ gnovm/pkg/gnolang/transpile_gno0p9.go | 21 ++++++-- gnovm/pkg/test/filetest.go | 4 +- gnovm/pkg/test/imports.go | 7 ++- 7 files changed, 70 insertions(+), 31 deletions(-) rename gnovm/adr/{lint_transpile.md => pr4264_lint_transpile.md} (100%) diff --git a/gnovm/adr/lint_transpile.md b/gnovm/adr/pr4264_lint_transpile.md similarity index 100% rename from gnovm/adr/lint_transpile.md rename to gnovm/adr/pr4264_lint_transpile.md diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 4dfb01a9091..de6bde3edb0 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -243,7 +243,7 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { startedAt := time.Now() didPanic := catchPanic(pkg.Dir, gnoPkgPath, io.Err(), func() { if modfile == nil || !modfile.Draft { - _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) + _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) if errs != nil { errsLint = errs io.ErrPrintln(errs) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index b16260cfada..dd64b58ff0e 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -29,7 +29,7 @@ import ( /* Linting. - Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). + Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). */ type processedPackage struct { @@ -164,6 +164,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { return commands.ExitCodeError(1) } + // See adr/pr4264_lint_transpile.md // STEP 1: ReadMemPackage() // Read MemPackage with pkgPath. pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) @@ -194,7 +195,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { var pn *gno.PackageNode var gopkg *types.Package var gofset *token.FileSet - var gofs []*ast.File + var gofs, _gofs, tgofs []*ast.File var errs error if false { println(gopkg, "is not used") @@ -211,7 +212,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - gopkg, gofset, gofs, errs = + gopkg, gofset, gofs, _gofs, tgofs, errs = lintTypeCheck(io, dir, mpkg, gs) if errs != nil { io.ErrPrintln(errs) @@ -232,7 +233,9 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { defer tm.Release() // Prepare Go AST for preprocessing. - errs = gno.PrepareGno0p9(gofset, gofs, mpkg) + allgofs := append(gofs, _gofs...) + allgofs = append(allgofs, tgofs...) + errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) if errs != nil { io.ErrPrintln(errs) hasError = true @@ -337,10 +340,10 @@ func lintTypeCheck( ) ( gopkg *types.Package, gofset *token.FileSet, - gofs []*ast.File, + gofs, _gofs, tgofs []*ast.File, errs error) { - gopkg, gofset, gofs, errs = gno.TypeCheckMemPackage(mpkg, testStore) + gopkg, gofset, gofs, _gofs, tgofs, errs = gno.TypeCheckMemPackage(mpkg, testStore) errors := multierr.Errors(errs) for _, err := range errors { switch err := err.(type) { diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 72ab81e5a79..57874d1f54f 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -15,7 +15,7 @@ import ( /* Type-checking (using go/types). - Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). + Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). */ // MemPackageGetter implements the GetMemPackage() method. It is a subset of @@ -30,7 +30,7 @@ type MemPackageGetter interface { // The syntax checking is performed entirely using Go's go/types package. // TODO: rename these to GoTypeCheck*, goTypeCheck*... func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( - pkg *types.Package, gofset *token.FileSet, gofs []*ast.File, errs error) { + pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { var gimp *gnoImporter gimp = &gnoImporter{ getter: getter, @@ -46,7 +46,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( all := true // type check all .gno files for mpkg (not for imports). strict := true // check gno.mod exists - pkg, gofset, gofs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) + pkg, gofset, gofs, _gofs, tgofs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) return } @@ -95,7 +95,7 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. } all := false // don't parse test files for imports. strict := false // don't check for gno.mod for imports. - pkg, _, _, errs := gimp.typeCheckMemPackage(mpkg, all, strict) + pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, all, strict) gimp.cache[path] = gnoImporterResult{pkg: pkg, err: errs} return pkg, errs } @@ -110,23 +110,27 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. // tests cannot be imported and used anyways. // - strict: If true errors on gno.mod version mismatch. func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, strict bool) ( - pkg *types.Package, gofset *token.FileSet, gofs []*ast.File, errs error) { + pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { - // STEP 1: Check gno.mod version. + // See adr/pr4264_lint_transpile.md + // STEP 2: Check gno.mod version. if strict { _, err := ParseCheckGnoMod(mpkg) if err != nil { - return nil, nil, nil, fmt.Errorf("gimp parse check gno.mod: %w", err) + return nil, nil, nil, nil, nil, fmt.Errorf("gimp parse check gno.mod: %w", err) } } - // STEP 2: Parse the mem package to Go AST. - gofset, gofs, errs = GoParseMemPackage(mpkg, all) + // STEP 3: Parse the mem package to Go AST. + gofset, gofs, _gofs, tgofs, errs = GoParseMemPackage(mpkg, all) if errs != nil { - return nil, nil, nil, fmt.Errorf("gimp Go mem package: %w", errs) + return nil, nil, nil, nil, nil, fmt.Errorf("gimp Go mem package: %w", errs) + } + if !all && (len(_gofs) > 0 || len(tgofs) > 0) { + panic("unexpected test files from GoParseMemPackage()") } - // STEP 2: Add .gnobuiltins.go file. + // STEP 3: Add .gnobuiltins.go file. file := &std.MemFile{ Name: ".gnobuiltins.go", Body: fmt.Sprintf(`package %s @@ -139,11 +143,11 @@ type realm interface{} // shim `, mpkg.Name), } - // STEP 2: Parse .gnobuiltins.go file. + // STEP 3: Parse .gnobuiltins.go file. const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var gof, err = parser.ParseFile( + var gmgof, err = parser.ParseFile( gofset, path.Join(mpkg.Path, file.Name), file.Body, @@ -151,11 +155,27 @@ type realm interface{} // shim if err != nil { panic("error parsing gotypecheck gnobuiltins.go file") } - gofs = append(gofs, gof) - // STEP 3: Type-check Gno0.9 AST in Go. + // STEP 4: Type-check Gno0.9 AST in Go (normal and _test.gno if all). + gofs = append(gofs, gmgof) pkg, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs, nil) - return pkg, gofset, gofs, gimp.errors + + // STEP 4: Type-check Gno0.9 AST in Go (xxx_test package if all). + // Each integration test is its own package. + for _, _gof := range _gofs { + gmgof.Name = _gof.Name // copy _test package name to gno.mod + gofs2 := []*ast.File{gmgof, _gof} + _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) + } + + // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if all). + // Each filetest is its own package. + for _, tgof := range tgofs { + gmgof.Name = tgof.Name // copy _filetest.gno package name to gno.mod + gofs2 := []*ast.File{gmgof, tgof} + _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) + } + return pkg, gofset, gofs, _gofs, tgofs, gimp.errors } func deleteOldIdents(idents map[string]func(), gof *ast.File) { diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 472664601c8..5ad8975b846 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -21,7 +21,7 @@ import ( /* Transpiling old Gno code to Gno 0.9. - Refer to the [Lint and Transpile ADR](./adr/lint_transpile.md). + Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). ParseCheckGnoMod() defined in pkg/gnolang/gnomod.go. */ @@ -33,8 +33,15 @@ import ( // Args: // - wtests: if true also parses and includes all *_test.gno // and *_filetest.gno files. +// +// Results: +// - gofs: all normal .gno files (and _test.gno files if wtests). +// - _gofs: all xxx_test package _test.gno files if wtests. +// - tgofs: all _testfile.gno test files. +// +// XXX move to pkg/gnolang/gotypecheck.go? func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( - gofset *token.FileSet, gofs []*ast.File, errs error) { + gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { gofset = token.NewFileSet() // This map is used to allow for function re-definitions, which are @@ -70,10 +77,16 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( } deleteOldIdents(delFunc, gof) // The *ast.File passed all filters. - gofs = append(gofs, gof) + if strings.HasSuffix(file.Name, "_filetest.gno") { + tgofs = append(tgofs, gof) + } else if strings.HasSuffix(gof.Name.String(), "_test") { + _gofs = append(_gofs, gof) + } else { + gofs = append(gofs, gof) + } } if errs != nil { - return gofset, gofs, errs + return gofset, gofs, _gofs, tgofs, errs } // END processing all files. return diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index 74bdaa89e9d..2c9b07a15f3 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -286,7 +286,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content }, } // Validate Gno syntax and type check. - if _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } @@ -322,7 +322,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content m.Store = tx // Validate Gno syntax and type check. - if _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index b5cf27e11d6..5583c5593d2 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -72,12 +72,15 @@ func StoreWithOptions( // the preprocessor make a slight modifications to the // AST. This needs to happen even for imports, because // the preprocessor requries imports also preprocessed. + // This is because the linter uses pkg/test/imports.go. const wtests = false // Tests don't matter for imports. - gofset, gofs, errs := gno.GoParseMemPackage(mpkg, wtests) + gofset, gofs, _gofs, tgofs, errs := gno.GoParseMemPackage(mpkg, wtests) if errs != nil { panic(fmt.Errorf("test store parsing: %w", errs)) } - errs = gno.PrepareGno0p9(gofset, gofs, mpkg) + allgofs := append(gofs, _gofs...) + allgofs = append(allgofs, tgofs...) + errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) if errs != nil { panic(fmt.Errorf("test store preparing AST: %w", errs)) } From f7688c5781ee501cb5d783fea00ac8289359bf41 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 13 May 2025 02:32:21 -0700 Subject: [PATCH 18/83] fix tests --- gnovm/cmd/gno/main_test.go | 12 ++- gnovm/cmd/gno/run_test.go | 8 +- gnovm/cmd/gno/testdata/lint/bad_import.txtar | 2 +- gnovm/cmd/gno/testdata/lint/file_error.txtar | 2 +- .../cmd/gno/testdata/lint/not_declared.txtar | 4 +- gnovm/cmd/gno/tool_lint.go | 79 ++++++++++--------- gnovm/cmd/gno/tool_lint_test.go | 22 +++--- gnovm/cmd/gno/util.go | 8 +- gnovm/pkg/gnolang/gnomod.go | 38 +++++++-- gnovm/pkg/gnolang/gotypecheck.go | 5 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 22 +++--- gnovm/pkg/test/filetest.go | 4 +- 12 files changed, 121 insertions(+), 85 deletions(-) diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 2ea3e31f977..73e9bb7abf7 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -14,6 +14,12 @@ import ( "github.com/stretchr/testify/require" ) +const div = "--------------------------------------------------------------------------------\n" + +func divHeader(label string) string { + return label + " " + div[len(label)+1:] +} + func TestMain_Gno(t *testing.T) { tc := []testMainCase{ {args: []string{""}, errShouldBe: "flag: help requested"}, @@ -69,7 +75,7 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { if stdoutShouldBeEmpty { require.Empty(t, mockOut.String(), "stdout should be empty") } else { - t.Log("stdout", mockOut.String()) + t.Log(divHeader("stdout"), mockOut.String()) if test.stdoutShouldContain != "" { require.Contains(t, mockOut.String(), test.stdoutShouldContain, "stdout should contain") } @@ -81,7 +87,7 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { if stderrShouldBeEmpty { require.Empty(t, mockErr.String(), "stderr should be empty") } else { - t.Log("stderr", mockErr.String()) + t.Log(divHeader("stderr"), mockErr.String()) if test.stderrShouldContain != "" { require.Contains(t, mockErr.String(), test.stderrShouldContain, "stderr should contain") } @@ -94,7 +100,7 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { defer func() { if r := recover(); r != nil { output := fmt.Sprintf("%v", r) - t.Log("recover", output) + t.Log(divHeader("recover"), output) require.False(t, recoverShouldBeEmpty, "should not panic") require.True(t, errShouldBeEmpty, "should not return an error") if test.recoverShouldContain != "" { diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index 711420ff1d5..a5a4be2e5aa 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -90,10 +90,10 @@ func TestRunApp(t *testing.T) { args: []string{"run", "../../tests/integ/several-files-multiple-errors/"}, stderrShouldContain: func() string { lines := []string{ - "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=2)", - "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=2)", - "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=2)", - "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=2)", + "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (panic=+go/scanner.ErrorList) (code=lintGnoError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (panic=+go/scanner.ErrorList) (code=lintGnoError)", + "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (panic=+go/scanner.ErrorList) (code=lintGnoError)", + "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (panic=+go/scanner.ErrorList) (code=lintGnoError)", } return strings.Join(lines, "\n") + "\n" }(), diff --git a/gnovm/cmd/gno/testdata/lint/bad_import.txtar b/gnovm/cmd/gno/testdata/lint/bad_import.txtar index e2c0431443c..a99fb237bf9 100644 --- a/gnovm/cmd/gno/testdata/lint/bad_import.txtar +++ b/gnovm/cmd/gno/testdata/lint/bad_import.txtar @@ -19,4 +19,4 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -bad_file.gno:3:8: unknown import path python (code=2) +bad_file.gno:3:8: unknown import path python (LoadImports) (code=lintGnoError) diff --git a/gnovm/cmd/gno/testdata/lint/file_error.txtar b/gnovm/cmd/gno/testdata/lint/file_error.txtar index 4fa50c6da81..ba531e2be72 100644 --- a/gnovm/cmd/gno/testdata/lint/file_error.txtar +++ b/gnovm/cmd/gno/testdata/lint/file_error.txtar @@ -20,4 +20,4 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -i_have_error_test.gno:6:7: name undefined_variable not declared (code=2) +i_have_error_test.gno:6:7: name undefined_variable not declared (code=lintPreprocessError) diff --git a/gnovm/cmd/gno/testdata/lint/not_declared.txtar b/gnovm/cmd/gno/testdata/lint/not_declared.txtar index ac56b27e0df..fd12fbd2362 100644 --- a/gnovm/cmd/gno/testdata/lint/not_declared.txtar +++ b/gnovm/cmd/gno/testdata/lint/not_declared.txtar @@ -18,5 +18,5 @@ module gno.land/p/demo/hello -- stdout.golden -- -- stderr.golden -- -bad_file.gno:4:2: undefined: hello (code=4) -bad_file.gno:4:2: name hello not declared (code=2) +bad_file.gno:4:2: undefined: hello (code=lintTypeCheckError) +bad_file.gno:4:2: name hello not declared (code=lintPreprocessError) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index dd64b58ff0e..13212d350b3 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -15,7 +15,6 @@ import ( "path" "path/filepath" "regexp" - rdebug "runtime/debug" "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" @@ -75,11 +74,13 @@ func (c *lintCmd) RegisterFlags(fs *flag.FlagSet) { type lintCode string const ( - lintUnknown lintCode = "lintUnknown" - lintGnoMod = "lintGnoMod" - lintGnoError = "lintGnoError" - lintParserError = "lintParserError" - lintTypeCheckError = "lintTypeCheckError" + lintUnknownError lintCode = "lintUnknownError" + lintReadError = "lintReadError" + lintImportError = "lintImportError" // XXX break this out + lintGnoModError = "lintGnoModError" + lintPreprocessError = "lintPreprocessError" + lintParserError = "lintParserError" + lintTypeCheckError = "lintTypeCheckError" // TODO: add new linter codes here. ) @@ -121,11 +122,13 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ) ppkgs := map[string]processedPackage{} - fmt.Println("linting directories...", dirs) + // TODO print progress when verbose. + // fmt.Println("linting directories...", dirs) //---------------------------------------- // STAGE 1: for _, dir := range dirs { - fmt.Printf("linting %q\n", dir) + // TODO print progress when verbose. + // fmt.Printf("linting %q\n", dir) if cmd.verbose { io.ErrPrintln(dir) } @@ -140,7 +143,8 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { mod, err := gnomod.ParseFilepath(fpath) if errors.Is(err, fs.ErrNotExist) { if cmd.autoGnomod { - mod, err = gnomod.ParseBytes("gno.mod", []byte(gno.GnoModDefault)) + modstr := gno.GenGnoModDefault("gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx") + mod, err = gnomod.ParseBytes("gno.mod", []byte(modstr)) if err != nil { panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) } @@ -154,7 +158,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } if err != nil { issue := lintIssue{ - Code: lintGnoMod, + Code: lintGnoModError, Confidence: 1, // ?? Location: fpath, Msg: err.Error(), @@ -171,15 +175,17 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { io.ErrPrintln(issueFromError( - dir, pkgPath, err, "ReadMemPackge").String()) + dir, pkgPath, err, lintReadError).String()) hasError = true continue } // Perform imports using the parent store. + // XXX "lintImportError" is obscure, try to + // find the cause as another lint*Error? if err := test.LoadImports(ts, mpkg); err != nil { io.ErrPrintln(issueFromError( - dir, pkgPath, err, "LoadImports").String()) + dir, pkgPath, err, lintImportError).String()) hasError = true continue } @@ -222,24 +228,21 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } - // If gno version is already 0.9, skip. - if mod.GetGno() == "0.9" { // XXX - return - } - // STEP 4: Prepare*() // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) defer tm.Release() // Prepare Go AST for preprocessing. - allgofs := append(gofs, _gofs...) - allgofs = append(allgofs, tgofs...) - errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) - if errs != nil { - io.ErrPrintln(errs) - hasError = true - return // Prepare must succeed. + if mod.GetGno() == "0.0" { + allgofs := append(gofs, _gofs...) + allgofs = append(allgofs, tgofs...) + errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) + if errs != nil { + io.ErrPrintln(errs) + hasError = true + return // Prepare must succeed. + } } // STEP 5: re-parse @@ -332,6 +335,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). +// Prints expected errors, and returns nil unless an unexpected error arises. func lintTypeCheck( io commands.IO, dir string, @@ -341,10 +345,12 @@ func lintTypeCheck( gopkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, - errs error) { + lerr error) { - gopkg, gofset, gofs, _gofs, tgofs, errs = gno.TypeCheckMemPackage(mpkg, testStore) - errors := multierr.Errors(errs) + var tcErrs error + gopkg, gofset, gofs, _gofs, tgofs, tcErrs = + gno.TypeCheckMemPackage(mpkg, testStore) + errors := multierr.Errors(tcErrs) for _, err := range errors { switch err := err.(type) { case types.Error: @@ -377,7 +383,7 @@ func lintTypeCheck( Location: loc, }) default: - io.ErrPrintfln("unknown error (%T): %s", err, err.Error()) + lerr = err return } } @@ -456,13 +462,12 @@ func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (di if r == nil { return } - rdebug.PrintStack() didPanic = true switch verr := r.(type) { case *gno.PreprocessError: err := verr.Unwrap() fmt.Fprintln(stderr, issueFromError( - dir, pkgPath, err, "panic=PreprocessError").String()) + dir, pkgPath, err, lintPreprocessError).String()) case error: errors := multierr.Errors(verr) for _, err := range errors { @@ -473,7 +478,7 @@ func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (di dir, pkgPath, errorInList, - "panic=+go/scanner.ErrorList", + lintParserError, ).String()) } } else { @@ -481,7 +486,7 @@ func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (di dir, pkgPath, err, - "panic=error", + lintUnknownError, ).String()) } } @@ -490,7 +495,7 @@ func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (di dir, pkgPath, errors.New(verr), - "panic=string", + lintUnknownError, ).String()) default: panic(r) @@ -501,10 +506,10 @@ func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (di return } -func issueFromError(dir, pkgPath string, err error, why string) lintIssue { +func issueFromError(dir, pkgPath string, err error, code lintCode) lintIssue { var issue lintIssue issue.Confidence = 1 - issue.Code = lintGnoError + issue.Code = code parsedError := strings.TrimSpace(err.Error()) parsedError = replaceWithDirPath(parsedError, pkgPath, dir) @@ -514,10 +519,10 @@ func issueFromError(dir, pkgPath string, err error, why string) lintIssue { if len(matches) > 0 { sourcepath := guessSourcePath(pkgPath, matches[1]) issue.Location = sourcepath + matches[2] - issue.Msg = strings.TrimSpace(matches[3]) + " (" + why + ")" + issue.Msg = strings.TrimSpace(matches[3]) } else { issue.Location = fmt.Sprintf("%s:0", filepath.Clean(pkgPath)) - issue.Msg = err.Error() + " (" + why + ")" + issue.Msg = err.Error() } return issue } diff --git a/gnovm/cmd/gno/tool_lint_test.go b/gnovm/cmd/gno/tool_lint_test.go index aaffcbaddff..dce3452ceeb 100644 --- a/gnovm/cmd/gno/tool_lint_test.go +++ b/gnovm/cmd/gno/tool_lint_test.go @@ -12,33 +12,33 @@ func TestLintApp(t *testing.T) { errShouldBe: "flag: help requested", }, { - args: []string{"lint", "../../tests/integ/run_main/"}, - stderrShouldContain: "./../../tests/integ/run_main: gno.mod file not found in current or any parent directory (code=1)", + args: []string{"lint", "../../tests/integ/run_main/", "-auto-gnomod=false"}, + stderrShouldContain: "../../tests/integ/run_main/gno.mod: could not read gno.mod file: stat ../../tests/integ/run_main/gno.mod: no such file or directory (code=lintGnoModError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/undefined_variable_test/undefined_variables_test.gno"}, - stderrShouldContain: "undefined_variables_test.gno:6:28: name toto not declared (code=2)", + stderrShouldContain: "undefined_variables_test.gno:6:28: name toto not declared (code=lintPreprocessError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/package_not_declared/main.gno"}, - stderrShouldContain: "main.gno:4:2: name fmt not declared (code=2)", + stderrShouldContain: "main.gno:4:2: name fmt not declared (code=lintPreprocessError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/several-lint-errors/main.gno"}, - stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5:5: expected ';', found example (code=3)\n../../tests/integ/several-lint-errors/main.gno:6", + stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5:5: expected ';', found example (code=lintParserError)\n../../tests/integ/several-lint-errors/main.gno:6", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/several-files-multiple-errors/main.gno"}, stderrShouldContain: func() string { lines := []string{ - "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=3)", - "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=3)", - "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=3)", - "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=3)", + "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=lintParserError)", } return strings.Join(lines, "\n") + "\n" }(), @@ -54,12 +54,12 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "../../tests/integ/invalid_gno_file/"}, - stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=2)", + stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=lintReadError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/typecheck_missing_return/"}, - stderrShouldContain: "../../tests/integ/typecheck_missing_return/main.gno:5:1: missing return (code=4)", + stderrShouldContain: "../../tests/integ/typecheck_missing_return/main.gno:5:1: missing return (code=lintTypeCheckError)", errShouldBe: "exit code: 1", }, { diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 697aa94b3c6..ea1097954af 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -27,7 +27,7 @@ func gnoFilesFromArgsRecursively(args []string) ([]string, error) { for _, argPath := range args { info, err := os.Stat(argPath) if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) + return nil, fmt.Errorf("gno: invalid file or package path %q: %w", argPath, err) } if !info.IsDir() { @@ -56,7 +56,7 @@ func gnoFilesFromArgs(args []string) ([]string, error) { for _, argPath := range args { info, err := os.Stat(argPath) if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) + return nil, fmt.Errorf("gno: invalid file or package path %q: %w", argPath, err) } if !info.IsDir() { @@ -125,7 +125,7 @@ func gnoPackagesFromArgsRecursively(args []string) ([]string, error) { for _, argPath := range args { info, err := os.Stat(argPath) if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) + return nil, fmt.Errorf("gno: invalid file or package path %q: %w", argPath, err) } if !info.IsDir() { @@ -169,7 +169,7 @@ func targetsFromPatterns(patterns []string) ([]string, error) { info, err := os.Stat(dirToSearch) if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) + return nil, fmt.Errorf("gno: invalid file or package path %q: %w", dirToSearch, err) } // If the pattern is a file or a directory diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index 76662b93594..011c796503f 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -1,7 +1,9 @@ package gnolang import ( + "bytes" "fmt" + "html/template" "io/fs" "os" "path/filepath" @@ -11,12 +13,35 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) +const gnomodTemplate = `{{/* +This is a comment in a Go template in pkg/gnolang/gnomod.go. +The gnomodTemplate is used with the 'text/template' package +to generate the final gno.mod file. */}} +module {{.PkgPath}} + +gno {{.GnoVersion}}` + +func GenGnoModLatest(pkgPath string) string { return genGnoMod(pkgPath, GnoVerLatest) } +func GenGnoModTesting(pkgPath string) string { return genGnoMod(pkgPath, GnoVerTesting) } +func GenGnoModDefault(pkgPath string) string { return genGnoMod(pkgPath, GnoVerDefault) } + +func genGnoMod(pkgPath string, gnoVersion string) string { + buf := new(bytes.Buffer) + tmpl := template.Must(template.New("").Parse(gnomodTemplate)) + err := tmpl.Execute(buf, struct { + PkgPath string + GnoVersion string + }{pkgPath, gnoVersion}) + if err != nil { + panic(fmt.Errorf("generating gno.mod: %w", err)) + } + return string(buf.Bytes()) +} + const ( - // gno.mod files assumed in testing/default contexts. - GnoModLatest = `go 0.9` // when gno.mod is missing for stdlibs. - GnoModTesting = `go 0.9` // when gno.mod is missing while testing. - GnoModDefault = `go 0.0` // when gno.mod is missing in general. - GnoVerDefault = `0.0` // when gno version isn't specified. + GnoVerLatest = `1.0` // current version + GnoVerTesting = `1.0` // version of our tests + GnoVerDefault = `0.0` // version undefined ) // ======================================== @@ -30,7 +55,8 @@ const ( func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { if IsStdlib(mpkg.Path) { // stdlib/extern packages are assumed up to date. - mod, _ = gnomod.ParseBytes("/gno.mod", []byte(GnoModLatest)) + modstr := GenGnoModLatest(mpkg.Path) + mod, _ = gnomod.ParseBytes("/gno.mod", []byte(modstr)) } else if mpkg.GetFile("gno.mod") == nil { // gno.mod doesn't exist. return nil, nil diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 57874d1f54f..20f467efdee 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -86,7 +86,6 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. if pkg, ok := gimp.cache[path]; ok { return pkg.pkg, pkg.err } - // fmt.Println("GNOIMPORTER IMPORTFROM > GETMEMPACKAGE", path) mpkg := gimp.getter.GetMemPackage(path) if mpkg == nil { err := importNotFoundError(path) @@ -117,14 +116,14 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, str if strict { _, err := ParseCheckGnoMod(mpkg) if err != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("gimp parse check gno.mod: %w", err) + return nil, nil, nil, nil, nil, err } } // STEP 3: Parse the mem package to Go AST. gofset, gofs, _gofs, tgofs, errs = GoParseMemPackage(mpkg, all) if errs != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("gimp Go mem package: %w", errs) + return nil, nil, nil, nil, nil, errs } if !all && (len(_gofs) > 0 || len(tgofs) > 0) { panic("unexpected test files from GoParseMemPackage()") diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 5ad8975b846..a8e9900bd45 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -425,8 +425,6 @@ func transpileGno0p9_part1(pkgPath string, gofs *token.FileSet, fname string, go return true }, nil) - fmt.Println("COMPARE", len(xforms1), len(xforms2)) - // Check that all xforms1 items were translated to xforms2. xfound = checkXforms(xforms1, xforms2, fname) return xfound, xforms2, err @@ -452,17 +450,19 @@ XFORMS1_LOOP: fmt.Println("xform2 item not found for xform1:", xform1) mismatch = true } - if !mismatch { - return found // good - } - // Failed check. - for xform1, _ := range xforms1 { - fmt.Println("xform1:", xform1) + if mismatch { + for xform1, _ := range xforms1 { + fmt.Println("xform1:", xform1) + } + for n2, xform2 := range xforms2 { + fmt.Println("xform2:", xform2, n2) + } + panic("xforms1 and xforms2 don't match") } - for n2, xform2 := range xforms2 { - fmt.Println("xform2:", xform2, n2) + if len(xforms1) != len(xforms2) { + panic("xforms1 and xforms2 length don't match") } - panic("xforms1 and xforms2 don't match") + return found // good } // The main Go AST transpiling logic to make Gno code Gno 0.9. diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index 2c9b07a15f3..af178cff975 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -230,7 +230,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content fname = filepath.Base(fname) // Eagerly load imports. - // This is executed using opts.Store, rather than the transaction store; + // LoadImports is run using opts.Store, rather than the transaction store; // it allows us to only have to load the imports once (and re-use the cached // versions). Running the tests in separate "transactions" means that they // don't get the parent store dirty. @@ -238,7 +238,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ - {Name: "gno.mod", Body: "gno 0.9"}, + {Name: "gno.mod", Body: gno.GenGnoModLatest(pkgPath)}, {Name: fname, Body: string(content)}, }, }); err != nil { From f8bfd7b288fdfe1d0d3de920c6dadd0c17f6febf Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 13 May 2025 08:20:56 -0700 Subject: [PATCH 19/83] fix tests --- gnovm/cmd/gno/run_test.go | 8 +-- gnovm/cmd/gno/test.go | 44 +++++++------- gnovm/cmd/gno/testdata/lint/bad_import.txtar | 2 +- gnovm/cmd/gno/testdata/lint/file_error.txtar | 3 +- gnovm/cmd/gno/testdata/lint/no_error.txtar | 3 +- gnovm/cmd/gno/testdata/lint/no_gnomod.txtar | 4 +- .../cmd/gno/testdata/lint/not_declared.txtar | 1 - gnovm/cmd/gno/testdata/test/flag_run.txtar | 1 - gnovm/cmd/gno/testdata/test/lint_error.txtar | 6 +- .../cmd/gno/testdata/test/lint_noerror.txtar | 22 +++++++ .../gno/testdata/test/no_path_flag_run.txtar | 3 +- .../gno/testdata/test/unknown_package.txtar | 3 +- gnovm/cmd/gno/tool_lint.go | 59 ++++++++++++------- gnovm/cmd/gno/tool_lint_test.go | 4 +- gnovm/cmd/gno/util.go | 20 ++++--- gnovm/pkg/gnolang/debugger.go | 21 +++++++ gnovm/pkg/gnolang/gnomod.go | 6 +- gnovm/pkg/gnolang/gotypecheck.go | 18 ++++++ gnovm/pkg/gnolang/gotypecheck_test.go | 34 +++++------ gnovm/pkg/gnolang/values.go | 1 + gnovm/pkg/test/errors.go | 16 +++++ gnovm/pkg/test/imports.go | 1 + gnovm/stdlibs/std/emit_event_test.go | 6 +- gnovm/tests/stdlibs/fmt/fmt_test.gno | 4 +- tm2/pkg/std/memfile.go | 4 +- 25 files changed, 194 insertions(+), 100 deletions(-) create mode 100644 gnovm/cmd/gno/testdata/test/lint_noerror.txtar create mode 100644 gnovm/pkg/test/errors.go diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index a5a4be2e5aa..70d16de04d9 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -90,10 +90,10 @@ func TestRunApp(t *testing.T) { args: []string{"run", "../../tests/integ/several-files-multiple-errors/"}, stderrShouldContain: func() string { lines := []string{ - "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (panic=+go/scanner.ErrorList) (code=lintGnoError)", - "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (panic=+go/scanner.ErrorList) (code=lintGnoError)", - "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (panic=+go/scanner.ErrorList) (code=lintGnoError)", - "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (panic=+go/scanner.ErrorList) (code=lintGnoError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=lintParserError)", } return strings.Join(lines, "\n") + "\n" }(), diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index de6bde3edb0..19c519f6b21 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -169,9 +169,10 @@ func (c *testCmd) RegisterFlags(fs *flag.FlagSet) { } func execTest(cmd *testCmd, args []string, io commands.IO) error { - // Show a help message by default. + + // Default to current directory if no args provided if len(args) == 0 { - return flag.ErrHelp + args = []string{"."} } // Guess opts.RootDir. @@ -233,43 +234,38 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { modfile, _ := gnomod.ParseDir(pkg.Dir) gnoPkgPath, ok := determinePkgPath(modfile, pkg.Dir, cmd.rootDir) if !ok { - io.ErrPrintfln("--- WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") + io.ErrPrintfln("WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") } // Read MemPackage and lint/typecheck/format. // (gno.mod will be read again). - var errsLint, errsTest error + var didPanic, didError bool memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) startedAt := time.Now() - didPanic := catchPanic(pkg.Dir, gnoPkgPath, io.Err(), func() { - if modfile == nil || !modfile.Draft { - _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) - if errs != nil { - errsLint = errs - io.ErrPrintln(errs) - } - } else if cmd.verbose { - io.ErrPrintfln("%s: module is draft, skipping type check", gnoPkgPath) + didPanic = catchPanic(pkg.Dir, gnoPkgPath, io.Err(), func() { + //XXX why would we skip type-checking for drafts? + //if modfile == nil || !modfile.Draft { + _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) + if errs != nil { + didError = true + io.ErrPrintln(errs) + return } - errs := test.Test(memPkg, pkg.Dir, opts) + //} else if cmd.verbose { + // io.ErrPrintfln("%s: module is draft, skipping type check", gnoPkgPath) + //} + errs = test.Test(memPkg, pkg.Dir, opts) if errs != nil { - errsTest = errs + didError = true io.ErrPrintln(errs) + return } }) // Print status with duration. duration := time.Since(startedAt) dstr := fmtDuration(duration) - if didPanic || errsLint != nil || errsTest != nil { - if errsLint != nil { - io.ErrPrintfln( - "%s: lint pkg: %v", pkg.Dir, errsLint) - } - if errsTest != nil { - io.ErrPrintfln( - "%s: test pkg: %v", pkg.Dir, errsTest) - } + if didPanic || didError { io.ErrPrintfln("FAIL %s \t%s", pkg.Dir, dstr) testErrCount++ if cmd.failfast { diff --git a/gnovm/cmd/gno/testdata/lint/bad_import.txtar b/gnovm/cmd/gno/testdata/lint/bad_import.txtar index a99fb237bf9..e58fcb3cc6a 100644 --- a/gnovm/cmd/gno/testdata/lint/bad_import.txtar +++ b/gnovm/cmd/gno/testdata/lint/bad_import.txtar @@ -19,4 +19,4 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -bad_file.gno:3:8: unknown import path python (LoadImports) (code=lintGnoError) +bad_file.gno:3:8: unknown import path python (code=lintImportError) diff --git a/gnovm/cmd/gno/testdata/lint/file_error.txtar b/gnovm/cmd/gno/testdata/lint/file_error.txtar index ba531e2be72..efb5054017b 100644 --- a/gnovm/cmd/gno/testdata/lint/file_error.txtar +++ b/gnovm/cmd/gno/testdata/lint/file_error.txtar @@ -20,4 +20,5 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -i_have_error_test.gno:6:7: name undefined_variable not declared (code=lintPreprocessError) +i_have_error_test.gno:6:7: undefined: undefined_variable (code=lintTypeCheckError) +i_have_error_test.gno:6:2: declared and not used: i (code=lintTypeCheckError) diff --git a/gnovm/cmd/gno/testdata/lint/no_error.txtar b/gnovm/cmd/gno/testdata/lint/no_error.txtar index 5dd3b164952..5e3e6db8a39 100644 --- a/gnovm/cmd/gno/testdata/lint/no_error.txtar +++ b/gnovm/cmd/gno/testdata/lint/no_error.txtar @@ -1,6 +1,6 @@ # testing simple gno lint command with any error -gno lint ./good_file.gno +gno lint . cmp stdout stdout.golden cmp stdout stderr.golden @@ -15,5 +15,6 @@ func main() { -- gno.mod -- module gno.land/p/demo/test +gno 0.9 -- stdout.golden -- -- stderr.golden -- diff --git a/gnovm/cmd/gno/testdata/lint/no_gnomod.txtar b/gnovm/cmd/gno/testdata/lint/no_gnomod.txtar index b5a046a7095..51462ad2b4b 100644 --- a/gnovm/cmd/gno/testdata/lint/no_gnomod.txtar +++ b/gnovm/cmd/gno/testdata/lint/no_gnomod.txtar @@ -1,6 +1,6 @@ # gno lint: no gnomod -! gno lint . +gno lint . cmp stdout stdout.golden cmp stderr stderr.golden @@ -14,4 +14,4 @@ func main() { -- stdout.golden -- -- stderr.golden -- -./.: parsing gno.mod at ./.: gno.mod file not found in current or any parent directory (code=1) +auto-generated "gno.mod" diff --git a/gnovm/cmd/gno/testdata/lint/not_declared.txtar b/gnovm/cmd/gno/testdata/lint/not_declared.txtar index fd12fbd2362..84778f6a1fb 100644 --- a/gnovm/cmd/gno/testdata/lint/not_declared.txtar +++ b/gnovm/cmd/gno/testdata/lint/not_declared.txtar @@ -19,4 +19,3 @@ module gno.land/p/demo/hello -- stdout.golden -- -- stderr.golden -- bad_file.gno:4:2: undefined: hello (code=lintTypeCheckError) -bad_file.gno:4:2: name hello not declared (code=lintPreprocessError) diff --git a/gnovm/cmd/gno/testdata/test/flag_run.txtar b/gnovm/cmd/gno/testdata/test/flag_run.txtar index 31cc10cf3a3..629a6479026 100644 --- a/gnovm/cmd/gno/testdata/test/flag_run.txtar +++ b/gnovm/cmd/gno/testdata/test/flag_run.txtar @@ -85,7 +85,6 @@ package run package run import ( - "fmt" "testing" ) diff --git a/gnovm/cmd/gno/testdata/test/lint_error.txtar b/gnovm/cmd/gno/testdata/test/lint_error.txtar index ff6bf3d6018..5b2af40cb61 100644 --- a/gnovm/cmd/gno/testdata/test/lint_error.txtar +++ b/gnovm/cmd/gno/testdata/test/lint_error.txtar @@ -1,9 +1,9 @@ -# Test with a valid _test.gno file +# Test with a valid _test.gno file with invalid file. ! gno test -v . -stdout 'hello123' -stderr 'PASS: TestAlwaysValid' +#stdout 'hello123' +#stderr 'PASS: TestAlwaysValid' stderr 'declared and not used: x' stderr 'FAIL' diff --git a/gnovm/cmd/gno/testdata/test/lint_noerror.txtar b/gnovm/cmd/gno/testdata/test/lint_noerror.txtar new file mode 100644 index 00000000000..84d76855ee0 --- /dev/null +++ b/gnovm/cmd/gno/testdata/test/lint_noerror.txtar @@ -0,0 +1,22 @@ +# Test with a valid _test.gno file. + +gno test -v . + +stdout 'hello123' +stderr 'PASS: TestAlwaysValid' + +-- valid.gno -- +package valid + +func fn() { + println("hello123") +} + +-- valid_test.gno -- +package valid + +import "testing" + +func TestAlwaysValid(t *testing.T) { + fn() +} diff --git a/gnovm/cmd/gno/testdata/test/no_path_flag_run.txtar b/gnovm/cmd/gno/testdata/test/no_path_flag_run.txtar index 3db2a4c9295..4c609a7b03d 100644 --- a/gnovm/cmd/gno/testdata/test/no_path_flag_run.txtar +++ b/gnovm/cmd/gno/testdata/test/no_path_flag_run.txtar @@ -83,7 +83,6 @@ package run package run import ( - "fmt" "testing" ) @@ -96,4 +95,4 @@ func TestRun(t *testing.T) { for _, tc := range cases { t.Run(tc, func(t *testing.T) {}) } -} \ No newline at end of file +} diff --git a/gnovm/cmd/gno/testdata/test/unknown_package.txtar b/gnovm/cmd/gno/testdata/test/unknown_package.txtar index 0611d3440a4..aa0f18c169f 100644 --- a/gnovm/cmd/gno/testdata/test/unknown_package.txtar +++ b/gnovm/cmd/gno/testdata/test/unknown_package.txtar @@ -3,7 +3,8 @@ ! gno test -v . ! stdout .+ -stderr 'contract.gno:3:8: unknown import path foobarbaz' +# XXX catch and convert to lintImportError +stderr 'contract.gno:3:8: could not import foobarbaz \(import not found: foobarbaz\) \(code=lintUnknownError\)' -- contract.gno -- package contract diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 13212d350b3..d8560c7b3c6 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -29,6 +29,13 @@ import ( /* Linting. Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). + + XXX Currently the linter only supports linting directories. In order to + support linting individual files, we need to refactor this code to work + with mempackages, not dirs, and cmd/gno/util.go needs to be refactored + to return mempackages rather than dirs. Commands like `gno lint a.gno + b.gno` should create a temporary package from just those files. We + could also load mempackages lazily for memory efficiency. */ type processedPackage struct { @@ -208,25 +215,27 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Run type checking - if !mod.Draft { - // STEP 2: ParseGnoMod() - // STEP 3: GoParse*() - // - // lintTypeCheck(mpkg) --> - // TypeCheckMemPackage(mpkg) --> - // imp.typeCheckMemPackage(mpkg) - // ParseGnoMod(mpkg); - // GoParseMemPackage(mpkg); - // g.cmd.Check(); - gopkg, gofset, gofs, _gofs, tgofs, errs = - lintTypeCheck(io, dir, mpkg, gs) - if errs != nil { - io.ErrPrintln(errs) - hasError = true - } - } else if cmd.verbose { - io.ErrPrintfln("%s: module is draft, skipping type check", dir) + // STEP 2: ParseGnoMod() + // STEP 3: GoParse*() + // + // lintTypeCheck(mpkg) --> + // TypeCheckMemPackage(mpkg) --> + // imp.typeCheckMemPackage(mpkg) + // ParseGnoMod(mpkg); + // GoParseMemPackage(mpkg); + // g.cmd.Check(); + //XXX why would we skip type-checking for drafts? + //if !mod.Draft { + gopkg, gofset, gofs, _gofs, tgofs, errs = + lintTypeCheck(io, dir, mpkg, gs) + if errs != nil { + // io.ErrPrintln(errs) already printed. + hasError = true + return } + //} else if cmd.verbose { + // io.ErrPrintfln("%s: module is draft, skipping type check", dir) + //} // STEP 4: Prepare*() // Construct machine for testing. @@ -294,7 +303,9 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { for _, dir := range dirs { ppkg, ok := ppkgs[dir] if !ok { - panic("where did it go") + // XXX fix this; happens when linting a file. + // XXX see comment on top of this file. + panic("missing package; gno lint currently only supports directories.") } mpkg, pn := ppkg.mpkg, ppkg.pn @@ -335,7 +346,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). -// Prints expected errors, and returns nil unless an unexpected error arises. +// Prints and returns errors. Panics upon an unexpected error. func lintTypeCheck( io commands.IO, dir string, @@ -347,9 +358,12 @@ func lintTypeCheck( gofs, _gofs, tgofs []*ast.File, lerr error) { + // gno.TypeCheckMemPackage(mpkg, testStore) var tcErrs error gopkg, gofset, gofs, _gofs, tgofs, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore) + + // Print errors, and return the first unexpected error. errors := multierr.Errors(tcErrs) for _, err := range errors { switch err := err.(type) { @@ -383,10 +397,11 @@ func lintTypeCheck( Location: loc, }) default: - lerr = err - return + panic(err) // unexpected. } } + + lerr = tcErrs return } diff --git a/gnovm/cmd/gno/tool_lint_test.go b/gnovm/cmd/gno/tool_lint_test.go index dce3452ceeb..be7c8187082 100644 --- a/gnovm/cmd/gno/tool_lint_test.go +++ b/gnovm/cmd/gno/tool_lint_test.go @@ -18,12 +18,12 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "../../tests/integ/undefined_variable_test/undefined_variables_test.gno"}, - stderrShouldContain: "undefined_variables_test.gno:6:28: name toto not declared (code=lintPreprocessError)", + stderrShouldContain: "../../tests/integ/undefined_variable_test/undefined_variables_test.gno:6:28: undefined: toto (code=lintTypeCheckError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/package_not_declared/main.gno"}, - stderrShouldContain: "main.gno:4:2: name fmt not declared (code=lintPreprocessError)", + stderrShouldContain: "../../tests/integ/package_not_declared/main.gno:4:2: undefined: fmt (code=lintTypeCheckError)", errShouldBe: "exit code: 1", }, { diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index ea1097954af..564cf1a5645 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -32,7 +32,7 @@ func gnoFilesFromArgsRecursively(args []string) ([]string, error) { if !info.IsDir() { if isGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) + paths = append(paths, cleanPath(argPath)) } continue @@ -40,7 +40,7 @@ func gnoFilesFromArgsRecursively(args []string) ([]string, error) { // Gather package paths from the directory err = walkDirForGnoFiles(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) + paths = append(paths, cleanPath(path)) }) if err != nil { return nil, fmt.Errorf("unable to walk dir: %w", err) @@ -61,7 +61,7 @@ func gnoFilesFromArgs(args []string) ([]string, error) { if !info.IsDir() { if isGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) + paths = append(paths, cleanPath(argPath)) } continue } @@ -73,7 +73,7 @@ func gnoFilesFromArgs(args []string) ([]string, error) { for _, f := range files { if isGnoFile(f) { path := filepath.Join(argPath, f.Name()) - paths = append(paths, ensurePathPrefix(path)) + paths = append(paths, cleanPath(path)) } } } @@ -81,11 +81,15 @@ func gnoFilesFromArgs(args []string) ([]string, error) { return paths, nil } -func ensurePathPrefix(path string) string { +// ensures that the path is absolute or starts with a dot. +// ensures that the path is a dir path. +func cleanPath(path string) string { if filepath.IsAbs(path) { return path } - + if strings.HasPrefix(path, ".") { + return path + } // cannot use path.Join or filepath.Join, because we need // to ensure that ./ is the prefix to pass to go build. // if not absolute. @@ -129,14 +133,14 @@ func gnoPackagesFromArgsRecursively(args []string) ([]string, error) { } if !info.IsDir() { - paths = append(paths, ensurePathPrefix(argPath)) + paths = append(paths, cleanPath(argPath)) continue } // Gather package paths from the directory err = walkDirForGnoFiles(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) + paths = append(paths, cleanPath(path)) }) if err != nil { return nil, fmt.Errorf("unable to walk dir: %w", err) diff --git a/gnovm/pkg/gnolang/debugger.go b/gnovm/pkg/gnolang/debugger.go index 22c110db7dd..28517bd830a 100644 --- a/gnovm/pkg/gnolang/debugger.go +++ b/gnovm/pkg/gnolang/debugger.go @@ -753,6 +753,27 @@ func debugLookup(m *Machine, name string) (tv TypedValue, ok bool) { return tv, false } + // XXX The following logic isn't necessary and it isn't correct either. + // XXX See `GetPathForName(Store, Name) ValuePath` in node.go, + // XXX get the path and pass it into the last block.GetPointerTo(). + // XXX That function will find the correct block by depth etc. + // XXX There was some latent bug for case: + // XXX '{in: "b 37\nc\np b\n", out: "(3 int)"},' (debugger test case #51) + // XXX which was revealed by some earlier commits regarding lines + // XXX (Node now has not just the starting .Pos but also .End.) + // XXX and is resolved by the following diff to values.go: + // XXX The exact bug probably doesn't matter, as the logic + // XXX should be replaced by the aforementioned block.GetPointerTo(). + // + // --- a/gnovm/pkg/gnolang/values.go + // +++ b/gnovm/pkg/gnolang/values.go + // @@ -2480,6 +2480,7 @@ func (b *Block) ExpandWith(alloc *Allocator, source BlockNode) { + // } + // } + // b.Values = values + // + b.Source = source // otherwise new variables won't show in print or debugger. + // } + // Position to the right block, i.e the first after the last fblock (if any). for i = len(m.Blocks) - 1; i >= 0; i-- { if len(fblocks) == 0 { diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index 011c796503f..e8e49fe6d4d 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -39,9 +39,9 @@ func genGnoMod(pkgPath string, gnoVersion string) string { } const ( - GnoVerLatest = `1.0` // current version - GnoVerTesting = `1.0` // version of our tests - GnoVerDefault = `0.0` // version undefined + GnoVerLatest = `0.9` // current version + GnoVerTesting = `0.9` // version of our tests + GnoVerDefault = `0.9` // no gno.mod ) // ======================================== diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 20f467efdee..53213a37750 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -95,6 +95,12 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. all := false // don't parse test files for imports. strict := false // don't check for gno.mod for imports. pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, all, strict) + if errs != nil { + // NOTE: + // Returning an error doesn't abort the type-checker. + // Panic instead to quit quickly. + panic(errs) + } gimp.cache[path] = gnoImporterResult{pkg: pkg, err: errs} return pkg, errs } @@ -158,6 +164,10 @@ type realm interface{} // shim // STEP 4: Type-check Gno0.9 AST in Go (normal and _test.gno if all). gofs = append(gofs, gmgof) pkg, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs, nil) + if gimp.errors != nil { + errs = gimp.errors + return + } // STEP 4: Type-check Gno0.9 AST in Go (xxx_test package if all). // Each integration test is its own package. @@ -165,6 +175,10 @@ type realm interface{} // shim gmgof.Name = _gof.Name // copy _test package name to gno.mod gofs2 := []*ast.File{gmgof, _gof} _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) + if gimp.errors != nil { + errs = gimp.errors + return + } } // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if all). @@ -173,6 +187,10 @@ type realm interface{} // shim gmgof.Name = tgof.Name // copy _filetest.gno package name to gno.mod gofs2 := []*ast.File{gmgof, tgof} _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) + if gimp.errors != nil { + errs = gimp.errors + return + } } return pkg, gofset, gofs, _gofs, tgofs, gimp.errors } diff --git a/gnovm/pkg/gnolang/gotypecheck_test.go b/gnovm/pkg/gnolang/gotypecheck_test.go index b7f06b0776e..e24812353d4 100644 --- a/gnovm/pkg/gnolang/gotypecheck_test.go +++ b/gnovm/pkg/gnolang/gotypecheck_test.go @@ -138,7 +138,7 @@ func TestTypeCheckMemPackage(t *testing.T) { errContains("assignment mismatch", "too many return values"), }, { - "TestsIgnored", + "TestsAlso", &std.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", @@ -151,13 +151,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { Name: "hello_test.gno", - Body: `This is not valid Gno code, but it doesn't matter because test - files are not checked.`, + Body: `This is not valid Gno code, and it matters.`, }, }, }, nil, - nil, + errContains("gno.land/p/demo/hello/hello_test.gno:1:1: expected 'package', found This"), }, { "ImportFailed", @@ -364,8 +363,7 @@ func TestTypeCheckMemPackage(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - format := false - err := TypeCheckMemPackage(tc.pkg, tc.getter, format) + _, _, _, _, _, err := TypeCheckMemPackage(tc.pkg, tc.getter) if tc.check == nil { assert.NoError(t, err) } else { @@ -399,21 +397,21 @@ func TestTypeCheckMemPackage_format(t *testing.T) { } mpkgGetter := mockPackageGetter{} - format := false - err := TypeCheckMemPackage(pkg, mpkgGetter, format) + _, _, _, _, _, err := TypeCheckMemPackage(pkg, mpkgGetter) assert.NoError(t, err) assert.Equal(t, input, pkg.Files[0].Body) // unchanged - expected := `package hello + /* XXX TypeChecker no longer does the formatting. + expected := `package hello -func Hello(name string) string { - return "hello" + name -} -` + func Hello(name string) string { + return "hello" + name + } + ` - format = true - err = TypeCheckMemPackage(pkg, mpkgGetter, format) - assert.NoError(t, err) - assert.NotEqual(t, input, pkg.Files[0].Body) - assert.Equal(t, expected, pkg.Files[0].Body) + _, _, _, _, _, _, err = TypeCheckMemPackage(pkg, mpkgGetter) + assert.NoError(t, err) + assert.NotEqual(t, input, pkg.Files[0].Body) + assert.Equal(t, expected, pkg.Files[0].Body) + */ } diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 54021302309..c625c4d8e03 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -2480,6 +2480,7 @@ func (b *Block) ExpandWith(alloc *Allocator, source BlockNode) { } } b.Values = values + b.Source = source // otherwise new variables won't show in print or debugger. } // NOTE: RefValue Object methods declared in ownership.go diff --git a/gnovm/pkg/test/errors.go b/gnovm/pkg/test/errors.go new file mode 100644 index 00000000000..f66aabb8b4c --- /dev/null +++ b/gnovm/pkg/test/errors.go @@ -0,0 +1,16 @@ +package test + +import "fmt" + +// XXX use it; this isn't used yet. +type TestImportError struct { + PkgPath string +} + +func (err TestImportError) Error() string { + return fmt.Sprintf("unknown package path %q", err.PkgPath) +} + +func (err TestImportError) String() string { + return fmt.Sprintf("TestImportError(%q)", err.Error()) +} diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 5583c5593d2..ec104fa48ac 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -147,6 +147,7 @@ func StoreWithOptions( }) return _processMemPackage(m2, mpkg, true) } + return nil, nil } diff --git a/gnovm/stdlibs/std/emit_event_test.go b/gnovm/stdlibs/std/emit_event_test.go index 05532d49707..7b4c8ae9d0e 100644 --- a/gnovm/stdlibs/std/emit_event_test.go +++ b/gnovm/stdlibs/std/emit_event_test.go @@ -21,8 +21,10 @@ func pushFuncFrame(m *gno.Machine, name gno.Name) { fd.SetLocation(gno.Location{ PkgPath: pkgPath, File: fileName, - Line: line, // fake unique line no - Column: 0, // fake column + Span: gno.Span{ // fake unique span. + Pos: gno.Pos{line, 0}, + End: gno.Pos{line, 100}, + }, }) line++ fv := &gno.FuncValue{Name: name, PkgPath: m.Package.PkgPath, Source: fd} diff --git a/gnovm/tests/stdlibs/fmt/fmt_test.gno b/gnovm/tests/stdlibs/fmt/fmt_test.gno index 8220ebf9b4c..7a60ae3a458 100644 --- a/gnovm/tests/stdlibs/fmt/fmt_test.gno +++ b/gnovm/tests/stdlibs/fmt/fmt_test.gno @@ -1328,7 +1328,7 @@ func TestStructPrinter(t *testing.T) { }{ {"%v", "{abc def 123}"}, {"%+v", "{a:abc b:def c:123}"}, - {"%#v", `fmt_test[fmt_test/fmt_test.gno:1315:1].T{a:"abc", b:"def", c:123}`}, + {"%#v", `fmt_test[fmt_test/fmt_test.gno:1315:1-1344:2].T{a:"abc", b:"def", c:123}`}, } for _, tt := range tests { out := fmt.Sprintf(tt.fmt, s) @@ -1591,7 +1591,7 @@ func TestNilDoesNotBecomeTyped(t *testing.T) { var a *A = nil var b B = B{} got := fmt.Sprintf(hideFromVet("%s %s %s %s %s"), nil, a, nil, b, nil) - const expect = "%!s() %!s(*fmt_test[fmt_test/fmt_test.gno:1588:1].A=) %!s() {} %!s()" + const expect = "%!s() %!s(*fmt_test[fmt_test/fmt_test.gno:1588:1-1598:2].A=) %!s() {} %!s()" if got != expect { t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got) } diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index fa653a7a772..427144afb7e 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -193,9 +193,9 @@ func (mpkg *MemPackage) IsEmpty() bool { // Write all files into dir. func (mpkg *MemPackage) WriteTo(dir string) error { - fmt.Printf("writing mempackage to %q:\n", dir) + // fmt.Printf("writing mempackage to %q:\n", dir) for _, mfile := range mpkg.Files { - fmt.Printf(" - %s (%d bytes)\n", mfile.Name, len(mfile.Body)) + // fmt.Printf(" - %s (%d bytes)\n", mfile.Name, len(mfile.Body)) fpath := filepath.Join(dir, mfile.Name) err := ioutil.WriteFile(fpath, []byte(mfile.Body), 0644) if err != nil { From c3ef149ca8a4a3f71594e46635c9032189ef7831 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 13 May 2025 17:21:59 -0700 Subject: [PATCH 20/83] fix gnovm tests; type-checking for test files work --- gnovm/cmd/gno/test.go | 22 ++++--- gnovm/pkg/gnolang/gotypecheck.go | 93 +++++++++++++++------------ gnovm/pkg/gnolang/transpile_gno0p9.go | 47 ++++++++++---- gnovm/pkg/test/imports.go | 10 ++- gnovm/pkg/test/test.go | 44 ++++++------- 5 files changed, 130 insertions(+), 86 deletions(-) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 19c519f6b21..1c1f02096a4 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -229,32 +229,34 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { continue } - // Determine gnoPkgPath by reading gno.mod from disk. + // Determine pkgPath by reading gno.mod from disk. // TODO: Have ReadMemPackage handle it. modfile, _ := gnomod.ParseDir(pkg.Dir) - gnoPkgPath, ok := determinePkgPath(modfile, pkg.Dir, cmd.rootDir) + pkgPath, ok := determinePkgPath(modfile, pkg.Dir, cmd.rootDir) if !ok { io.ErrPrintfln("WARNING: unable to read package path from gno.mod or gno root directory; try creating a gno.mod file") } - // Read MemPackage and lint/typecheck/format. + // Read MemPackage. + mpkg := gno.MustReadMemPackage(pkg.Dir, pkgPath) + + // Lint/typecheck/format. // (gno.mod will be read again). var didPanic, didError bool - memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) startedAt := time.Now() - didPanic = catchPanic(pkg.Dir, gnoPkgPath, io.Err(), func() { + didPanic = catchPanic(pkg.Dir, pkgPath, io.Err(), func() { //XXX why would we skip type-checking for drafts? //if modfile == nil || !modfile.Draft { - _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, memPkg, opts.TestStore) + _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore) if errs != nil { didError = true io.ErrPrintln(errs) return } //} else if cmd.verbose { - // io.ErrPrintfln("%s: module is draft, skipping type check", gnoPkgPath) + // io.ErrPrintfln("%s: module is draft, skipping type check", pkgPath) //} - errs = test.Test(memPkg, pkg.Dir, opts) + errs = test.Test(mpkg, pkg.Dir, opts) if errs != nil { didError = true io.ErrPrintln(errs) @@ -286,8 +288,8 @@ func determinePkgPath(modfile *gnomod.File, dir, rootDir string) (string, bool) if modfile != nil { return modfile.Module.Mod.Path, true } - if path := pkgPathFromRootDir(dir, rootDir); path != "" { - return path, true + if pkgPath := pkgPathFromRootDir(dir, rootDir); pkgPath != "" { + return pkgPath, true } // unable to read pkgPath from gno.mod, use a deterministic path. return "gno.land/r/test", false // XXX: gno.land hardcoded for convenience. diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 53213a37750..4f87d69fccf 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -8,6 +8,7 @@ import ( "go/types" "path" "slices" + "strings" "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" @@ -28,13 +29,13 @@ type MemPackageGetter interface { // mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. -// TODO: rename these to GoTypeCheck*, goTypeCheck*... func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { var gimp *gnoImporter gimp = &gnoImporter{ - getter: getter, - cache: map[string]gnoImporterResult{}, + pkgPath: mpkg.Path, + getter: getter, + cache: map[string]gnoImporterResult{}, cfg: &types.Config{ Error: func(err error) { gimp.Error(err) @@ -44,9 +45,9 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( } gimp.cfg.Importer = gimp - all := true // type check all .gno files for mpkg (not for imports). - strict := true // check gno.mod exists - pkg, gofset, gofs, _gofs, tgofs, errs = gimp.typeCheckMemPackage(mpkg, all, strict) + pmode := ParseModeAll // type check all .gno files + strict := true // check gno.mod exists + pkg, gofset, gofs, _gofs, tgofs, errs = gimp.typeCheckMemPackage(mpkg, pmode, strict) return } @@ -60,10 +61,12 @@ type gnoImporterResult struct { // gimp remembers. // gimp. type gnoImporter struct { - getter MemPackageGetter - cache map[string]gnoImporterResult - cfg *types.Config - errors error // multierr + // when importing self (from xxx_test package) include *_test.gno. + pkgPath string + getter MemPackageGetter + cache map[string]gnoImporterResult + cfg *types.Config + errors error // multierr } // Unused, but satisfies the Importer interface. @@ -81,27 +84,32 @@ type importNotFoundError string func (e importNotFoundError) Error() string { return "import not found: " + string(e) } // ImportFrom returns the imported package for the given import -// path when imported by a package file located in dir. -func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Package, error) { - if pkg, ok := gimp.cache[path]; ok { +// pkgPath when imported by a package file located in dir. +func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*types.Package, error) { + if pkg, ok := gimp.cache[pkgPath]; ok { return pkg.pkg, pkg.err } - mpkg := gimp.getter.GetMemPackage(path) + mpkg := gimp.getter.GetMemPackage(pkgPath) if mpkg == nil { - err := importNotFoundError(path) - gimp.cache[path] = gnoImporterResult{err: err} + err := importNotFoundError(pkgPath) + gimp.cache[pkgPath] = gnoImporterResult{err: err} return nil, err } - all := false // don't parse test files for imports. + var pmode = ParseModeProduction // don't parse test files for imports... + if gimp.pkgPath == pkgPath { + // ...unless importing self from a *_test.gno + // file with package name xxx_test. + pmode = ParseModeIntegration + } strict := false // don't check for gno.mod for imports. - pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, all, strict) + pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, pmode, strict) if errs != nil { // NOTE: // Returning an error doesn't abort the type-checker. // Panic instead to quit quickly. panic(errs) } - gimp.cache[path] = gnoImporterResult{pkg: pkg, err: errs} + gimp.cache[pkgPath] = gnoImporterResult{pkg: pkg, err: errs} return pkg, errs } @@ -110,11 +118,10 @@ func (gimp *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types. // Returns parsed *types.Package, *token.FileSet, []*ast.File. // // Args: -// - all: If true add all *_test.gno and *_testfile.gno files. -// Generally should be set to false when importing because -// tests cannot be imported and used anyways. +// - pmode: ParseModeAll for type-checking all files. +// ParseModeProduction when type-checking imports. // - strict: If true errors on gno.mod version mismatch. -func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, strict bool) ( +func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMode, strict bool) ( pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { // See adr/pr4264_lint_transpile.md @@ -127,13 +134,16 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, all bool, str } // STEP 3: Parse the mem package to Go AST. - gofset, gofs, _gofs, tgofs, errs = GoParseMemPackage(mpkg, all) + gofset, gofs, _gofs, tgofs, errs = GoParseMemPackage(mpkg, pmode) if errs != nil { return nil, nil, nil, nil, nil, errs } - if !all && (len(_gofs) > 0 || len(tgofs) > 0) { + if pmode == ParseModeProduction && (len(_gofs) > 0 || len(tgofs) > 0) { panic("unexpected test files from GoParseMemPackage()") } + if pmode == ParseModeIntegration && (len(_gofs) > 0 || len(tgofs) > 0) { + panic("unexpected xxx_test and *_filetest.gno tests") + } // STEP 3: Add .gnobuiltins.go file. file := &std.MemFile{ @@ -161,7 +171,7 @@ type realm interface{} // shim panic("error parsing gotypecheck gnobuiltins.go file") } - // STEP 4: Type-check Gno0.9 AST in Go (normal and _test.gno if all). + // STEP 4: Type-check Gno0.9 AST in Go (normal, and _test.gno if ParseModeIntegration). gofs = append(gofs, gmgof) pkg, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs, nil) if gimp.errors != nil { @@ -169,24 +179,27 @@ type realm interface{} // shim return } - // STEP 4: Type-check Gno0.9 AST in Go (xxx_test package if all). - // Each integration test is its own package. - for _, _gof := range _gofs { - gmgof.Name = _gof.Name // copy _test package name to gno.mod - gofs2 := []*ast.File{gmgof, _gof} - _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) - if gimp.errors != nil { - errs = gimp.errors - return - } + // STEP 4: Type-check Gno0.9 AST in Go (xxx_test package if ParseModeAll). + if strings.HasSuffix(mpkg.Name, "_test") { + // e.g. When running a filetest // PKGPATH: xxx_test. + } else { + gmgof.Name = ast.NewIdent(mpkg.Name + "_test") + defer func() { gmgof.Name = ast.NewIdent(mpkg.Name) }() // revert + } + _gofs2 := append(_gofs, gmgof) + _, _ = gimp.cfg.Check(mpkg.Path, gofset, _gofs2, nil) + if gimp.errors != nil { + errs = gimp.errors + return } - // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if all). + // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if ParseModeAll). // Each filetest is its own package. + defer func() { gmgof.Name = ast.NewIdent(mpkg.Name) }() // revert for _, tgof := range tgofs { - gmgof.Name = tgof.Name // copy _filetest.gno package name to gno.mod - gofs2 := []*ast.File{gmgof, tgof} - _, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs2, nil) + gmgof.Name = tgof.Name // may be anything. + tgof2 := []*ast.File{gmgof, tgof} + _, _ = gimp.cfg.Check(mpkg.Path, gofset, tgof2, nil) if gimp.errors != nil { errs = gimp.errors return diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index a8e9900bd45..c183f6d4829 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -26,13 +26,23 @@ import ( ParseCheckGnoMod() defined in pkg/gnolang/gnomod.go. */ +type ParseMode int + +const ( + // no test files. + ParseModeProduction ParseMode = iota + // production and test files when xxx_test tests import xxx package. + ParseModeIntegration + // all files even including *_filetest.gno; for linting and testing. + ParseModeAll +) + // ======================================== // Go parse the Gno source in mpkg to Go's *token.FileSet and // []ast.File with `go/parser`. // // Args: -// - wtests: if true also parses and includes all *_test.gno -// and *_filetest.gno files. +// - pmode: see documentation for ParseMode. // // Results: // - gofs: all normal .gno files (and _test.gno files if wtests). @@ -40,7 +50,7 @@ import ( // - tgofs: all _testfile.gno test files. // // XXX move to pkg/gnolang/gotypecheck.go? -func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( +func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { gofset = token.NewFileSet() @@ -56,12 +66,22 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( if !strings.HasSuffix(file.Name, ".gno") { continue } - // Ignore _test/_filetest.gno files unless wtests. - if !wtests && - (false || - strings.HasSuffix(file.Name, "_test.gno") || - strings.HasSuffix(file.Name, "_filetest.gno")) { - continue + // Ignore _test/_filetest.gno files depending. + switch pmode { + case ParseModeProduction: + if strings.HasSuffix(file.Name, "_test.gno") || + strings.HasSuffix(file.Name, "_filetest.gno") { + continue + } + case ParseModeIntegration: + if strings.HasSuffix(file.Name, "_filetest.gno") { + continue + } + case ParseModeAll: + // include all + default: + panic("should not happen") + } // Go parse file. const parseOpts = parser.ParseComments | @@ -80,8 +100,13 @@ func GoParseMemPackage(mpkg *std.MemPackage, wtests bool) ( if strings.HasSuffix(file.Name, "_filetest.gno") { tgofs = append(tgofs, gof) } else if strings.HasSuffix(gof.Name.String(), "_test") { - _gofs = append(_gofs, gof) - } else { + if pmode == ParseModeIntegration { + // never wanted these gofs. + // (we do want other *_test.gno in gofs) + } else { + _gofs = append(_gofs, gof) + } + } else { // normal *_test.gno here for integration testing. gofs = append(gofs, gof) } } diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index ec104fa48ac..7202b59efa8 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -40,7 +40,11 @@ func Store( baseStore storetypes.CommitStore, resStore gno.Store, ) { - return StoreWithOptions(rootDir, output, StoreOptions{}) + return StoreWithOptions( + rootDir, + output, + StoreOptions{}, + ) } // ======================================== @@ -74,7 +78,8 @@ func StoreWithOptions( // the preprocessor requries imports also preprocessed. // This is because the linter uses pkg/test/imports.go. const wtests = false // Tests don't matter for imports. - gofset, gofs, _gofs, tgofs, errs := gno.GoParseMemPackage(mpkg, wtests) + gofset, gofs, _gofs, tgofs, errs := gno.GoParseMemPackage( + mpkg, gno.ParseModeAll) if errs != nil { panic(fmt.Errorf("test store parsing: %w", errs)) } @@ -85,7 +90,6 @@ func StoreWithOptions( panic(fmt.Errorf("test store preparing AST: %w", errs)) } } - m.Store.AddMemPackage(mpkg) return m.PreprocessFiles( mpkg.Name, mpkg.Path, diff --git a/gnovm/pkg/test/test.go b/gnovm/pkg/test/test.go index 945fba6c535..853aad8c215 100644 --- a/gnovm/pkg/test/test.go +++ b/gnovm/pkg/test/test.go @@ -205,27 +205,27 @@ func tee(ptr *io.Writer, dst io.Writer) (revert func()) { } } -// Test runs tests on the specified memPkg. +// Test runs tests on the specified mpkg. // fsDir is the directory on filesystem of package; it's used in case opts.Sync // is enabled, and points to the directory where the files are contained if they // are to be updated. // opts is a required set of options, which is often shared among different // tests; you can use [NewTestOptions] for a common base configuration. -func Test(memPkg *std.MemPackage, fsDir string, opts *TestOptions) error { +func Test(mpkg *std.MemPackage, fsDir string, opts *TestOptions) error { opts.outWriter.w = opts.Output opts.outWriter.errW = opts.Error var errs error // Eagerly load imports. - if err := LoadImports(opts.TestStore, memPkg); err != nil { + if err := LoadImports(opts.TestStore, mpkg); err != nil { return err } // Stands for "test", "integration test", and "filetest". // "integration test" are the test files with `package xxx_test` (they are // not necessarily integration tests, it's just for our internal reference.) - tset, itset, itfiles, ftfiles := parseMemPackageTests(memPkg) + tset, itset, itfiles, ftfiles := parseMemPackageTests(mpkg) // Testing with *_test.gno if len(tset.Files)+len(itset.Files) > 0 { @@ -237,7 +237,7 @@ func Test(memPkg *std.MemPackage, fsDir string, opts *TestOptions) error { // Run test files in pkg. if len(tset.Files) > 0 { - err := opts.runTestFiles(memPkg, tset, gs) + err := opts.runTestFiles(mpkg, tset, gs) if err != nil { errs = multierr.Append(errs, err) } @@ -246,8 +246,8 @@ func Test(memPkg *std.MemPackage, fsDir string, opts *TestOptions) error { // Test xxx_test pkg. if len(itset.Files) > 0 { itPkg := &std.MemPackage{ - Name: memPkg.Name + "_test", - Path: memPkg.Path + "_test", + Name: mpkg.Name + "_test", + Path: mpkg.Path + "_test", Files: itfiles, } @@ -303,7 +303,7 @@ func Test(memPkg *std.MemPackage, fsDir string, opts *TestOptions) error { } func (opts *TestOptions) runTestFiles( - memPkg *std.MemPackage, + mpkg *std.MemPackage, files *gno.FileSet, gs gno.TransactionStore, ) (errs error) { @@ -321,7 +321,7 @@ func (opts *TestOptions) runTestFiles( } }() - tests := loadTestFuncs(memPkg.Name, files) + tests := loadTestFuncs(mpkg.Name, files) var alloc *gno.Allocator if opts.Metrics { @@ -331,12 +331,12 @@ func (opts *TestOptions) runTestFiles( opts.TestStore.SetLogStoreOps(nil) // Check if we already have the package - it may have been eagerly loaded. - m = Machine(gs, opts.WriterForStore(), memPkg.Path, opts.Debug) + m = Machine(gs, opts.WriterForStore(), mpkg.Path, opts.Debug) m.Alloc = alloc - if gs.GetMemPackage(memPkg.Path) == nil { - m.RunMemPackage(memPkg, true) + if gs.GetMemPackage(mpkg.Path) == nil { + m.RunMemPackage(mpkg, true) } else { - m.SetActivePackage(gs.GetPackage(memPkg.Path, false)) + m.SetActivePackage(gs.GetPackage(mpkg.Path, false)) } pv := m.Package @@ -352,7 +352,7 @@ func (opts *TestOptions) runTestFiles( // - Run the test files before this for loop (but persist it to store; // RunFiles doesn't do that currently) // - Wrap here. - m = Machine(gs, opts.WriterForStore(), memPkg.Path, opts.Debug) + m = Machine(gs, opts.WriterForStore(), mpkg.Path, opts.Debug) m.Alloc = alloc.Reset() m.SetActivePackage(pv) @@ -386,7 +386,7 @@ func (opts *TestOptions) runTestFiles( Type: gno.Sel(testingcx, "InternalTest"), Elts: gno.KeyValueExprs{ // XXX Consider this. - // {Key: gno.X("Name"), Value: gno.Str(memPkg.Path + "/" + tf.Filename + "." + tf.Name)}, + // {Key: gno.X("Name"), Value: gno.Str(mpkg.Path + "/" + tf.Filename + "." + tf.Name)}, {Key: gno.X("Name"), Value: gno.Str(tf.Name)}, {Key: gno.X("F"), Value: gno.Nx(tf.Name)}, }, @@ -481,12 +481,12 @@ func loadTestFuncs(pkgName string, tfiles *gno.FileSet) (rt []testFunc) { return } -// parseMemPackageTests parses test files (skipping filetests) in the memPkg. -func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet, itfiles, ftfiles []*std.MemFile) { +// parseMemPackageTests parses test files (skipping filetests) in the mpkg. +func parseMemPackageTests(mpkg *std.MemPackage) (tset, itset *gno.FileSet, itfiles, ftfiles []*std.MemFile) { tset = &gno.FileSet{} itset = &gno.FileSet{} var errs error - for _, mfile := range memPkg.Files { + for _, mfile := range mpkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // skip this file. } @@ -502,17 +502,17 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet, itf switch { case strings.HasSuffix(mfile.Name, "_filetest.gno"): ftfiles = append(ftfiles, mfile) - case strings.HasSuffix(mfile.Name, "_test.gno") && memPkg.Name == string(n.PkgName): + case strings.HasSuffix(mfile.Name, "_test.gno") && mpkg.Name == string(n.PkgName): tset.AddFiles(n) - case strings.HasSuffix(mfile.Name, "_test.gno") && memPkg.Name+"_test" == string(n.PkgName): + case strings.HasSuffix(mfile.Name, "_test.gno") && mpkg.Name+"_test" == string(n.PkgName): itset.AddFiles(n) itfiles = append(itfiles, mfile) - case memPkg.Name == string(n.PkgName): + case mpkg.Name == string(n.PkgName): // normal package file default: panic(fmt.Sprintf( "expected package name [%s] or [%s_test] but got [%s] file [%s]", - memPkg.Name, memPkg.Name, n.PkgName, mfile)) + mpkg.Name, mpkg.Name, n.PkgName, mfile)) } } if errs != nil { From da16108b9c9742af9250aeb91bb9bef60454bfcc Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 15 May 2025 06:56:57 -0700 Subject: [PATCH 21/83] intermediate... --- gnovm/pkg/gnolang/files_test.go | 9 +- gnovm/pkg/gnolang/machine.go | 5 +- gnovm/pkg/gnolang/nodes.go | 46 +- gnovm/pkg/gnolang/preprocess.go | 1232 ++++++------------- gnovm/pkg/gnolang/realm.go | 2 + gnovm/pkg/gnolang/type_check.go | 49 +- gnovm/pkg/gnolang/types.go | 15 +- gnovm/stdlibs/crypto/bech32/bech32_test.gno | 2 +- gnovm/stdlibs/generated.go | 82 ++ gnovm/stdlibs/testing/base/fuzz.gno | 284 +++++ gnovm/stdlibs/testing/base/fuzz_test.gno | 168 +++ gnovm/stdlibs/testing/base/match.gno | 165 +++ gnovm/stdlibs/testing/base/random.gno | 72 ++ gnovm/stdlibs/testing/base/random_test.gno | 98 ++ gnovm/stdlibs/testing/base/testing.gno | 384 ++++++ gnovm/stdlibs/testing/base/testing.go | 18 + gnovm/stdlibs/testing/testing.gno | 358 +----- gnovm/tests/files/alloc_5.gno | 3 + gnovm/tests/files/alloc_6.gno | 3 + gnovm/tests/files/alloc_6a.gno | 3 + misc/genstd/package_sort.go | 3 +- 21 files changed, 1758 insertions(+), 1243 deletions(-) create mode 100644 gnovm/stdlibs/testing/base/fuzz.gno create mode 100644 gnovm/stdlibs/testing/base/fuzz_test.gno create mode 100644 gnovm/stdlibs/testing/base/match.gno create mode 100644 gnovm/stdlibs/testing/base/random.gno create mode 100644 gnovm/stdlibs/testing/base/random_test.gno create mode 100644 gnovm/stdlibs/testing/base/testing.gno create mode 100644 gnovm/stdlibs/testing/base/testing.go diff --git a/gnovm/pkg/gnolang/files_test.go b/gnovm/pkg/gnolang/files_test.go index 627d7157d84..2878965210e 100644 --- a/gnovm/pkg/gnolang/files_test.go +++ b/gnovm/pkg/gnolang/files_test.go @@ -66,10 +66,17 @@ func TestFiles(t *testing.T) { return nil } subTestName := path + isHidden := strings.HasPrefix(path, ".") + if isHidden { + t.Run(subTestName, func(t *testing.T) { + t.Skip("skipping hidden") + }) + return nil + } isLong := strings.HasSuffix(path, "_long.gno") if isLong && testing.Short() { t.Run(subTestName, func(t *testing.T) { - t.Skip("skipping in -short") + t.Skip("skipping long (-short)") }) return nil } diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 82e34a00929..a7d35a43274 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -811,8 +811,9 @@ func (m *Machine) EvalStaticTypeOf(last BlockNode, x Expr) Type { if debug { m.Printf("Machine.EvalStaticTypeOf(%v, %v)\n", last, x) } - // X must have been preprocessed. - if x.GetAttribute(ATTR_PREPROCESSED) == nil { + // X must have been preprocessed or a predefined func lit expr. + if x.GetAttribute(ATTR_PREPROCESSED) == nil && + x.GetAttribute(ATTR_PREPROCESS_SKIPPED) == nil { panic(fmt.Sprintf( "Machine.EvalStaticTypeOf(x) expression not yet preprocessed: %s", x.String())) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index a7bca79b844..7d3a16fc63f 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -122,19 +122,21 @@ type Name string type GnoAttribute string +// XXX once everything is done, convert to a uint64 bitflag. const ( - ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" - ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" - ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" - ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" - ATTR_IOTA GnoAttribute = "ATTR_IOTA" - ATTR_HEAP_DEFINES GnoAttribute = "ATTR_HEAP_DEFINES" // []Name heap items. - ATTR_HEAP_USES GnoAttribute = "ATTR_HEAP_USES" // []Name heap items used. - ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" - ATTR_LAST_BLOCK_STMT GnoAttribute = "ATTR_LAST_BLOCK_STMT" - ATTR_GLOBAL GnoAttribute = "ATTR_GLOBAL" - ATTR_PACKAGE_REF GnoAttribute = "ATTR_PACKAGE_REF" - ATTR_PACKAGE_DECL GnoAttribute = "ATTR_PACKAGE_DECL" + ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" + ATTR_PREPROCESS_SKIPPED GnoAttribute = "ATTR_PREPROCESS_SKIPPED" + ATTR_PREPROCESS_INCOMPLETE GnoAttribute = "ATTR_PREPROCESS_INCOMPLETE" + ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" + ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" + ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" + ATTR_IOTA GnoAttribute = "ATTR_IOTA" + ATTR_HEAP_DEFINES GnoAttribute = "ATTR_HEAP_DEFINES" // []Name heap items. + ATTR_HEAP_USES GnoAttribute = "ATTR_HEAP_USES" // []Name heap items used. + ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" + ATTR_LAST_BLOCK_STMT GnoAttribute = "ATTR_LAST_BLOCK_STMT" + ATTR_PACKAGE_REF GnoAttribute = "ATTR_PACKAGE_REF" + ATTR_PACKAGE_DECL GnoAttribute = "ATTR_PACKAGE_DECL" ) // Embedded in each Node. @@ -177,6 +179,14 @@ func (attr *Attributes) DelAttribute(key GnoAttribute) { delete(attr.data, key) } +func (attr *Attributes) GetAttributeKeys() []GnoAttribute { + res := make([]GnoAttribute, 0, len(attr.data)) + for key, _ := range attr.data { + res = append(res, key) + } + return res +} + func (attr *Attributes) String() string { panic("should not use") // node should override Pos/Span/Location methods. } @@ -1563,7 +1573,7 @@ type BlockNode interface { GetValueRef(Store, Name, bool) *TypedValue GetStaticTypeOf(Store, Name) Type GetStaticTypeOfAt(Store, ValuePath) Type - Predefine(bool, Name) + Reserve(bool, Name) Define(Name, TypedValue) Define2(bool, Name, Type, TypedValue) GetBody() Body @@ -1903,14 +1913,14 @@ func (sb *StaticBlock) GetLocalIndex(n Name) (uint16, bool) { // Implemented BlockNode. // This method is too slow for runtime, but it is used // during preprocessing to compute types. -// If skipPredefined, skips over names that are only predefined. -// Returns nil if not defined. -func (sb *StaticBlock) GetValueRef(store Store, n Name, skipPredefined bool) *TypedValue { +// If ignoreReserved, skips over names that are only reserved (and neither predefined nor defined). +// Returns nil if not found. +func (sb *StaticBlock) GetValueRef(store Store, n Name, ignoreReserved bool) *TypedValue { idx, ok := sb.GetLocalIndex(n) bb := &sb.Block bp := sb.GetParentNode(store) for { - if ok && (!skipPredefined || sb.Types[idx] != nil) { + if ok && (!ignoreReserved || sb.Types[idx] != nil) { return bb.GetPointerToInt(store, int(idx)).TV } else if bp != nil { idx, ok = bp.GetLocalIndex(n) @@ -1939,7 +1949,7 @@ func (sb *StaticBlock) Define(n Name, tv TypedValue) { } // Set type to nil, only reserving the name. -func (sb *StaticBlock) Predefine(isConst bool, n Name) { +func (sb *StaticBlock) Reserve(isConst bool, n Name) { _, exists := sb.GetLocalIndex(n) if !exists { sb.Define2(isConst, n, nil, anyValue(nil)) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ae89dde55c3..c5f598e17bc 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -17,23 +17,26 @@ const ( blankIdentifier = "_" ) -// In the case of a *FileSet, some declaration steps have to happen -// in a restricted parallel way across all the files. -// Anything predefined or preprocessed here get skipped during the Preprocess -// phase. +// Predefine (initStaticBlocks) and partially evaluates all names +// not inside function bodies. +// +// This function must be called on *FileSets because declarations +// in file sets may be unordered. func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // First, initialize all file nodes and connect to package node. // This will also reserve names on BlockNode.StaticBlock by - // calling StaticBlock.Predefine(). + // calling StaticBlock.Reserve(). + // + // NOTE: The calls to .Reserve() in initStaticBlock() below only + // reserve the name for determining the value path index. What comes + // later after this for-loop is a partial definition for *FuncDecl + // function declarations which will get filled out later during + // preprocessing. for _, fn := range fset.Files { setNodeLines(fn) setNodeLocations(pn.PkgPath, string(fn.Name), fn) initStaticBlocks(store, pn, fn) } - // NOTE: The calls to .Predefine() above is more of a name reservation, - // and what comes later in PredefineFileset() below is a second type of - // pre-defining mixed with defining, where recursive types are defined - // first and then filled out later. // NOTE: much of what follows is duplicated for a single *FileNode // in the main Preprocess translation function. Keep synced. @@ -53,8 +56,8 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } // recursively predefine dependencies. - d2, _ := predefineNow(store, fn, d) - fn.Decls[i] = d2 + predefineRecursively(store, fn, d) + fn.Decls[i] = d } } } @@ -72,8 +75,8 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } // recursively predefine dependencies. - d2, _ := predefineNow(store, fn, d) - fn.Decls[i] = d2 + predefineRecursively(store, fn, d) + fn.Decls[i] = d } } } @@ -91,8 +94,8 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } // recursively predefine dependencies. - d2, _ := predefineNow(store, fn, d) - fn.Decls[i] = d2 + predefineRecursively(store, fn, d) + fn.Decls[i] = d } } } @@ -107,35 +110,55 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { continue } + // Split multiple value decls into separate ones. + // NOTE: As a strange quirk of Go, intra-dependent + // value declarations like `var a, b, c = 1, a, b` is + // only allowed at the package level, but not within a + // function. Gno2 may allow this type of declaration, + // and when it does the following splitting logic will + // need to be duplicated in the Preprocessor. if vd, ok := d.(*ValueDecl); ok && len(vd.NameExprs) > 1 && len(vd.Values) == len(vd.NameExprs) { + var iota_ any + if len(vd.Attributes.data) > 0 { + // TODO: use a uint64 bitflag and faster operations. + keys := vd.GetAttributeKeys() + for _, key := range keys { + switch key { + case ATTR_IOTA: + iota_ = vd.GetAttribute(key) + default: + // defensive. + panic("unexpected attribute") + } + } + } split := make([]Decl, len(vd.NameExprs)) - for j := range vd.NameExprs { - base := vd.Copy().(*ValueDecl) - base.NameExprs = NameExprs{NameExpr{ - Attributes: base.NameExprs[j].Attributes, - Path: base.NameExprs[j].Path, - Name: base.NameExprs[j].Name, - Type: NameExprTypeDefine, - }} - - if j < len(base.Values) { - base.Values = Exprs{base.Values[j].Copy().(Expr)} + part := &ValueDecl{ + NameExprs: NameExprs{{ + Attributes: vd.NameExprs[j].Attributes, + Path: vd.NameExprs[j].Path, + Name: vd.NameExprs[j].Name, + Type: NameExprTypeDefine, + }}, + Type: vd.Type, + Values: Exprs{vd.Values[j].Copy().(Expr)}, + Const: vd.Const, } - - split[j], _ = predefineNow(store, fn, base) + if iota_ != nil { + part.SetAttribute(ATTR_IOTA, iota_) + } + predefineRecursively(store, fn, part) + split[j] = part } - fn.Decls = append(fn.Decls[:i], append(split, fn.Decls[i+1:]...)...) //nolint:makezero - i += len(vd.NameExprs) + i += len(vd.NameExprs) - 1 + continue + } else { + // recursively predefine dependencies. + predefineRecursively(store, fn, d) continue } - - d.SetAttribute(ATTR_GLOBAL, true) - // recursively predefine dependencies. - d2, _ := predefineNow(store, fn, d) - - fn.Decls[i] = d2 } } } @@ -172,7 +195,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // if loopvar, will promote to // NameExprTypeHeapDefine later. nx.Type = NameExprTypeDefine - last.Predefine(false, ln) + last.Reserve(false, ln) } } } @@ -193,7 +216,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } if nn != blankIdentifier { nx.Type = NameExprTypeDefine - last.Predefine(false, nn) + last.Reserve(false, nn) } case *ValueDecl: last2 := skipFile(last) @@ -204,13 +227,13 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { continue } nx.Type = NameExprTypeDefine - last2.Predefine(n.Const, nn) + last2.Reserve(n.Const, nn) } case *TypeDecl: last2 := skipFile(last) nx := &n.NameExpr nx.Type = NameExprTypeDefine - last2.Predefine(true, n.Name) + last2.Reserve(true, n.Name) case *FuncDecl: if n.IsMethod { if n.Recv.Name == "" || n.Recv.Name == blankIdentifier { @@ -234,7 +257,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } nx := &n.NameExpr nx.Type = NameExprTypeDefine - pkg.Predefine(false, n.Name) + pkg.Reserve(false, n.Name) pkg.UnassignableNames = append(pkg.UnassignableNames, n.Name) } case *FuncTypeExpr: @@ -270,7 +293,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { ifs := ns[len(ns)-1].(*IfStmt) // anything declared in ifs are copied. for _, n := range ifs.GetBlockNames() { - last.Predefine(false, n) + last.Reserve(false, n) } case *RangeStmt: if n.Op == DEFINE { @@ -278,14 +301,14 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { nx := n.Key.(*NameExpr) if nx.Name != blankIdentifier { nx.Type = NameExprTypeDefine - last.Predefine(false, nx.Name) + last.Reserve(false, nx.Name) } } if n.Value != nil { nx := n.Value.(*NameExpr) if nx.Name != blankIdentifier { nx.Type = NameExprTypeDefine - last.Predefine(false, nx.Name) + last.Reserve(false, nx.Name) } } } @@ -293,7 +316,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { for i := range n.Type.Params { px := &n.Type.Params[i].NameExpr px.Type = NameExprTypeDefine - last.Predefine(false, px.Name) + last.Reserve(false, px.Name) } for i := range n.Type.Results { rx := &n.Type.Results[i].NameExpr @@ -302,7 +325,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { rx.Name = Name(rn) } rx.Type = NameExprTypeDefine - last.Predefine(false, rx.Name) + last.Reserve(false, rx.Name) } case *SwitchStmt: // n.Varname is declared in each clause. @@ -316,7 +339,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { ss := ns[len(ns)-1].(*SwitchStmt) // anything declared in ss.init are copied. for _, n := range ss.GetBlockNames() { - last.Predefine(false, n) + last.Reserve(false, n) } if ss.IsTypeSwitch { if ss.VarName != "" { @@ -325,7 +348,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // > Switch varnames cannot be // captured as heap items. // [test](../gnovm/tests/files/closure11_known.gno) - last.Predefine(false, ss.VarName) + last.Reserve(false, ss.VarName) } } else { if ss.VarName != "" { @@ -335,7 +358,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { case *FuncDecl: if n.IsMethod { n.Recv.NameExpr.Type = NameExprTypeDefine - n.Predefine(false, n.Recv.Name) + n.Reserve(false, n.Recv.Name) } for i := range n.Type.Params { px := &n.Type.Params[i].NameExpr @@ -343,7 +366,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { panic("should not happen") } px.Type = NameExprTypeDefine - n.Predefine(false, px.Name) + n.Reserve(false, px.Name) } for i := range n.Type.Results { rx := &n.Type.Results[i].NameExpr @@ -352,7 +375,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { rx.Name = Name(rn) } rx.Type = NameExprTypeDefine - n.Predefine(false, rx.Name) + n.Reserve(false, rx.Name) } } return n, TRANS_CONTINUE @@ -528,7 +551,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { _, ok := last.GetLocalIndex(ln) if !ok { // initial declaration to be re-defined. - last.Predefine(false, ln) + last.Reserve(false, ln) } else { // do not redeclare. } @@ -553,22 +576,12 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { checkValDefineMismatch(cd) } - isGlobal := true - - for i := len(ns) - 1; i > 0; i-- { - if _, ok := ns[i].(*FuncDecl); ok { - isGlobal = false - } - } - - d.SetAttribute(ATTR_GLOBAL, isGlobal) - // recursively predefine dependencies. - d2, ppd := predefineNow(store, last, d) - if ppd { - return d2, TRANS_SKIP + preprocessed := predefineRecursively(store, last, d) + if preprocessed { + return d, TRANS_SKIP } else { - return d2, TRANS_CONTINUE + return d, TRANS_CONTINUE } } @@ -688,6 +701,12 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { case *FuncLitExpr: // retrieve cached function type. ft := evalStaticType(store, last, &n.Type).(*FuncType) + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + for _, p := range ns { + p.SetAttribute(ATTR_PREPROCESS_INCOMPLETE, true) + } + return n, TRANS_SKIP + } // push func body block. pushInitBlock(n, &last, &stack) // define parameters in new block. @@ -791,7 +810,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *FuncDecl: // retrieve cached function type. - // the type and receiver are already set in predefineNow. + // the type and receiver are already set in predefineRecursively. ft := getType(&n.Type).(*FuncType) // push func body block. @@ -847,8 +866,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { } else { // recursively predefine // dependencies. - d2, _ := predefineNow(store, n, d) - n.Decls[i] = d2 + predefineRecursively(store, n, d) + n.Decls[i] = d } } } @@ -864,8 +883,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { } else { // recursively predefine // dependencies. - d2, _ := predefineNow(store, n, d) - n.Decls[i] = d2 + predefineRecursively(store, n, d) + n.Decls[i] = d } } } @@ -881,8 +900,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { } else { // recursively predefine // dependencies. - d2, _ := predefineNow(store, n, d) - n.Decls[i] = d2 + predefineRecursively(store, n, d) + n.Decls[i] = d } } } @@ -897,8 +916,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { } else { // recursively predefine // dependencies. - d2, _ := predefineNow(store, n, d) - n.Decls[i] = d2 + predefineRecursively(store, n, d) + n.Decls[i] = d } } } @@ -930,7 +949,9 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { case TRANS_LEAVE: // mark as preprocessed so that it can be used // in evalStaticType(store,). - n.SetAttribute(ATTR_PREPROCESSED, true) + if n.GetAttribute(ATTR_PREPROCESS_INCOMPLETE) == nil { + n.SetAttribute(ATTR_PREPROCESSED, true) + } // Defer pop block from stack. // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK @@ -2243,11 +2264,23 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *TypeDecl: - // Construct new Type, where any recursive - // references refer to the old Type declared - // during *TypeDecl:ENTER. Then, copy over the - // values, completing the recursion. + // 'tmp' is a newly constructed type value, where + // any recursive references refer to the + // original type constructed by predefineRecursively() + // during during *TypeDecl:ENTER. + // + // For recursive definitions 'tmp' is a new + // unnamed type that is different than the + // original, but its elements will contain the + // original. It is later copied back into the + // original type, thus completing the recursive + // definition. (thus called 'tmp') tmp := evalStaticType(store, last, n.Type) + // 'dst' is the actual original type structure + // as contructed by predefineRecursively(). + // + // In short, the relationship between tmp and dst is: + // `type dst tmp`. dst := last.GetValueRef(store, n.Name, true).GetType() switch dst := dst.(type) { case *FuncType: @@ -2265,24 +2298,21 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { case *StructType: *dst = *(tmp.(*StructType)) case *DeclaredType: - // if store has this type, use that. - tid := DeclaredTypeID(lastpn.PkgPath, last.GetLocation(), n.Name) - exists := false - if dt := store.GetTypeSafe(tid); dt != nil { - dst = dt.(*DeclaredType) - last.GetValueRef(store, n.Name, true).SetType(dst) - exists = true - } - if !exists { - // otherwise construct new *DeclaredType. - // NOTE: this is where declared types are - // actually instantiated, not in + if n.IsAlias { + // Nothing to do. + } else { + // Construct a temporary new *DeclaredType + // and copy value to dst to keep the original pointer. + // + // NOTE: this is where the structured value + // (e.g. *ArrayType, *StructType) of declared + // types are actually instantiated, not in // machine.go:runDeclaration(). - dt2 := declareWith(lastpn.PkgPath, last, n.Name, tmp) + tmp2 := declareWith(lastpn.PkgPath, last, n.Name, tmp) // if !n.IsAlias { // not sure why this was here. - dt2.Seal() + tmp2.Seal() // } - *dst = *dt2 + *dst = *tmp2 } case PrimitiveType: dst = tmp.(PrimitiveType) @@ -3162,10 +3192,9 @@ func copyFromFauxBlock(bn BlockNode, orig BlockNode) { } } -// Evaluates the value of x which is expected to be a typeval. +// Evaluates (constructs) the value of x which is expected to be a typeval. // Caches the result as an attribute of x. -// To discourage mis-use, expects x to already be -// preprocessed. +// To discourage mis-use, expects x to already be preprocessed. func evalStaticType(store Store, last BlockNode, x Expr) Type { if t, ok := x.GetAttribute(ATTR_TYPE_VALUE).(Type); ok { return t @@ -3760,92 +3789,6 @@ func convertConst(store Store, last BlockNode, n Node, cx *ConstExpr, t Type) { } } -func assertTypeDeclNoCycle(store Store, last BlockNode, td *TypeDecl, stack *[]Name) { - assertTypeDeclNoCycle2(store, last, td.Type, stack, false, td.IsAlias) -} - -func assertTypeDeclNoCycle2(store Store, last BlockNode, x Expr, stack *[]Name, indirect bool, isAlias bool) { - if x == nil { - panic("unexpected nil expression when checking for type declaration cycles") - } - - var lastX Expr - defer func() { - if _, ok := lastX.(*NameExpr); ok { - // pop stack - *stack = (*stack)[:len(*stack)-1] - } - }() - - switch cx := x.(type) { - case *NameExpr: - var msg string - - // Function to build the error message - buildMessage := func() string { - for j := range *stack { - msg += fmt.Sprintf("%s -> ", (*stack)[j]) - } - return msg + string(cx.Name) // Append the current name last - } - - // Check for existence of cx.Name in stack - findCycle := func() { - for _, n := range *stack { - if n == cx.Name { - msg = buildMessage() - panic(fmt.Sprintf("invalid recursive type: %s", msg)) - } - } - } - - if indirect && !isAlias { - *stack = (*stack)[:0] - } else { - findCycle() - *stack = append(*stack, cx.Name) - lastX = cx - } - - return - case *SelectorExpr: - assertTypeDeclNoCycle2(store, last, cx.X, stack, indirect, isAlias) - case *StarExpr: - assertTypeDeclNoCycle2(store, last, cx.X, stack, true, isAlias) - case *FieldTypeExpr: - assertTypeDeclNoCycle2(store, last, cx.Type, stack, indirect, isAlias) - case *ArrayTypeExpr: - if cx.Len != nil { - assertTypeDeclNoCycle2(store, last, cx.Len, stack, indirect, isAlias) - } - assertTypeDeclNoCycle2(store, last, cx.Elt, stack, indirect, isAlias) - case *SliceTypeExpr: - assertTypeDeclNoCycle2(store, last, cx.Elt, stack, true, isAlias) - case *InterfaceTypeExpr: - for i := range cx.Methods { - assertTypeDeclNoCycle2(store, last, &cx.Methods[i], stack, indirect, isAlias) - } - case *ChanTypeExpr: - assertTypeDeclNoCycle2(store, last, cx.Value, stack, true, isAlias) - case *FuncTypeExpr: - for i := range cx.Params { - assertTypeDeclNoCycle2(store, last, &cx.Params[i], stack, true, isAlias) - } - for i := range cx.Results { - assertTypeDeclNoCycle2(store, last, &cx.Results[i], stack, true, isAlias) - } - case *MapTypeExpr: - assertTypeDeclNoCycle2(store, last, cx.Key, stack, true, isAlias) - assertTypeDeclNoCycle2(store, last, cx.Value, stack, true, isAlias) - case *StructTypeExpr: - for i := range cx.Fields { - assertTypeDeclNoCycle2(store, last, &cx.Fields[i], stack, indirect, isAlias) - } - default: - } - return -} - // 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 @@ -3854,329 +3797,113 @@ func assertTypeDeclNoCycle2(store Store, last BlockNode, x Expr, stack *[]Name, // NOTE: has no side effects except for the case of composite // type expressions, which must get preprocessed for inner // composite type eliding to work. -func findUndefined(store Store, last BlockNode, x Expr) (un Name) { - return findUndefined2(store, last, x, nil, true) -} - -// finds the next undefined identifier and returns it if it is global -func findUndefined2SkipLocals(store Store, last BlockNode, x Expr, t Type) Name { - name := findUndefinedGlobal(store, last, x, t) - - if name == "" { - return "" - } - - existsLocal := func(name Name, bn BlockNode) bool { - curr := bn - for { - currNames := curr.GetBlockNames() - - if slices.Contains(currNames, name) { - return true - } - - newcurr := bn.GetStaticBlock().GetParentNode(store) - - if curr == newcurr { - return false - } - - curr = newcurr - - if curr == nil { - return false - } - - _, isFile := curr.(*FileNode) - - if isFile { - return false - } - } - } - - pkg := packageOf(last) - - if _, _, ok := pkg.FileSet.GetDeclForSafe(name); !ok { - return "" - } - - isLocal := existsLocal(name, last) - - if isLocal { - return "" - } - - return name -} - -func findUndefinedStmt(store Store, last BlockNode, stmt Stmt, t Type) Name { - switch s := stmt.(type) { - case *TypeDecl: - un := findUndefined2SkipLocals(store, last, s.Type, t) - - if un != "" { - return un - } - case *ValueDecl: - un := findUndefined2SkipLocals(store, last, s.Type, t) - - if un != "" { - return un - } - for _, rh := range s.Values { - un := findUndefined2SkipLocals(store, last, rh, t) - - if un != "" { - return un - } - } - case *DeclStmt: - for _, rh := range s.Body { - un := findUndefinedStmt(store, last, rh, t) - - if un != "" { - return un - } - } - case *IncDecStmt: - un := findUndefined2SkipLocals(store, last, s.X, t) - - if un != "" { - return un - } - case *BlockStmt: - for _, rh := range s.Body { - un := findUndefinedStmt(store, s, rh, t) - - if un != "" { - return un - } - } - case *DeferStmt: - un := findUndefined2SkipLocals(store, last, s.Call.Func, t) - - if un != "" { - return un - } - - for _, rh := range s.Call.Args { - un = findUndefined2SkipLocals(store, last, rh, t) - - if un != "" { - return un - } - } - case *SwitchStmt: - un := findUndefined2SkipLocals(store, last, s.X, t) - if un != "" { - return un - } - - un = findUndefinedStmt(store, last, s.Init, t) - if un != "" { - return un - } - - for _, b := range s.Clauses { - b := b - un = findUndefinedStmt(store, s, &b, t) - - if un != "" { - return un - } - } - case *SwitchClauseStmt: - for _, rh := range s.Cases { - un := findUndefined2SkipLocals(store, last, rh, t) - - if un != "" { - return un - } - } - - for _, b := range s.Body { - un := findUndefinedStmt(store, last, b, t) - - if un != "" { - return un - } - } - - case *ExprStmt: - return findUndefined2SkipLocals(store, last, s.X, t) - case *AssignStmt: - for _, rh := range s.Rhs { - un := findUndefined2SkipLocals(store, last, rh, t) - - if un != "" { - return un - } - } - case *IfStmt: - un := findUndefinedStmt(store, last, s.Init, t) - if un != "" { - return un - } - - un = findUndefined2SkipLocals(store, last, s.Cond, t) - if un != "" { - return un - } - - un = findUndefinedStmt(store, last, &s.Else, t) - if un != "" { - return un - } - - un = findUndefinedStmt(store, last, &s.Then, t) - if un != "" { - return un - } - case *IfCaseStmt: - for _, b := range s.Body { - un := findUndefinedStmt(store, last, b, t) - - if un != "" { - return un - } - } - case *ReturnStmt: - for _, b := range s.Results { - un := findUndefined2SkipLocals(store, last, b, t) - if un != "" { - return un - } - } - case *RangeStmt: - un := findUndefined2SkipLocals(store, last, s.X, t) - if un != "" { - return un - } - - for _, b := range s.Body { - un := findUndefinedStmt(store, last, b, t) - if un != "" { - return un - } - } - case *ForStmt: - un := findUndefinedStmt(store, s, s.Init, t) - if un != "" { - return un - } - - un = findUndefined2SkipLocals(store, s, s.Cond, t) - if un != "" { - return un - } - - un = findUndefinedStmt(store, s, s.Post, t) - if un != "" { - return un - } - - for _, b := range s.Body { - un := findUndefinedStmt(store, last, b, t) - if un != "" { - return un - } - } - case *BranchStmt: - case nil: - return "" - default: - panic(fmt.Sprintf("findUndefinedStmt: %T not supported", s)) - } - return "" +// +// Args: +// - direct: If true x must not be a *NameExpr in stack/defining (illegal direct recursion). +// - t: for composite type eliding +func findUndefinedV(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool, t Type) (un Name) { + return findUndefinedAny(store, last, x, stack, defining, direct, false, t) } -func getGlobalValueRef(sb BlockNode, store Store, n Name) *TypedValue { - sbb := sb.GetStaticBlock() - idx, ok := sb.GetLocalIndex(n) - bb := &sb.GetStaticBlock().Block - bp := sb.GetParentNode(store) - - for { - if ok && sbb.Types[idx] != nil && (bp == nil || bp.GetParentNode(store) == nil) { - return bb.GetPointerToInt(store, int(idx)).TV - } else if bp != nil { - idx, ok = bp.GetLocalIndex(n) - sbb = bp.GetStaticBlock() - bb = sbb.GetBlock() - bp = bp.GetParentNode(store) - } else { - return nil - } - } +func findUndefinedT(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool) (un Name) { + return findUndefinedAny(store, last, x, stack, defining, direct, true, nil) } -func findUndefinedGlobal(store Store, last BlockNode, x Expr, t Type) (un Name) { +func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool, astype bool, t Type) (un Name) { if x == nil { return } switch cx := x.(type) { case *NameExpr: - if tv := getGlobalValueRef(last, store, cx.Name); tv != nil { - return - } - if _, ok := UverseNode().GetLocalIndex(cx.Name); ok { // XXX NOTE even if the name is shadowed by a file // level declaration, it is fine to return here as it - // will be predefined later. + // will be predefined later and fail then. + return + } + /* + if _, ok := defining[cx.Name]; !ok { + return cx.Name + } + */ + if direct { + if astype { + if _, ok := defining[cx.Name]; ok { + panic("RECURSIVE" + string(cx.Name)) // XXX + } + if tv := last.GetValueRef(store, cx.Name, true); tv != nil { + return + } + } else { + if tv := last.GetValueRef(store, cx.Name, true); tv == nil { + return cx.Name + panic("RECURSIVE") + fmt.Println("NAME", cx, "DEFINED (OK)") + return + } + return + } + } else { + } + if tv := last.GetValueRef(store, cx.Name, true); tv != nil { return } - return cx.Name case *BasicLitExpr: return case *BinaryExpr: - un = findUndefinedGlobal(store, last, cx.Left, nil) + un = findUndefinedV(store, last, cx.Left, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedGlobal(store, last, cx.Right, nil) + un = findUndefinedV(store, last, cx.Right, stack, defining, direct, nil) if un != "" { return } case *SelectorExpr: - return findUndefinedGlobal(store, last, cx.X, nil) + return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *SliceExpr: - un = findUndefinedGlobal(store, last, cx.X, nil) + un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } if cx.Low != nil { - un = findUndefinedGlobal(store, last, cx.Low, nil) + un = findUndefinedV(store, last, cx.Low, stack, defining, direct, nil) if un != "" { return } } if cx.High != nil { - un = findUndefinedGlobal(store, last, cx.High, nil) + un = findUndefinedV(store, last, cx.High, stack, defining, direct, nil) if un != "" { return } } if cx.Max != nil { - un = findUndefinedGlobal(store, last, cx.Max, nil) + un = findUndefinedV(store, last, cx.Max, stack, defining, direct, nil) if un != "" { return } } case *StarExpr: - return findUndefinedGlobal(store, last, cx.X, nil) + // NOTE: *StarExpr can either mean dereference, or a pointer type. + // It's not only confusing for new developers, it causes complexity + // in type checking. A *StarExpr is indirect as a type. + if astype { + return findUndefinedT(store, last, cx.X, stack, defining, false) + } else { + return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) + } case *RefExpr: - return findUndefinedGlobal(store, last, cx.X, nil) + return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *TypeAssertExpr: - un = findUndefinedGlobal(store, last, cx.X, nil) + un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } - return findUndefinedGlobal(store, last, cx.Type, nil) + return findUndefinedT(store, last, cx.Type, stack, defining, direct) case *UnaryExpr: - return findUndefinedGlobal(store, last, cx.X, nil) + return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *CompositeLitExpr: var ct Type if cx.Type == nil { @@ -4186,7 +3913,7 @@ func findUndefinedGlobal(store Store, last BlockNode, x Expr, t Type) (un Name) ct = t cx.Type = constType(cx, t) } else { - un = findUndefinedGlobal(store, last, cx.Type, nil) + un = findUndefinedT(store, last, cx.Type, stack, defining, direct) if un != "" { return } @@ -4203,18 +3930,18 @@ func findUndefinedGlobal(store Store, last BlockNode, x Expr, t Type) (un Name) switch ct.Kind() { case ArrayKind, SliceKind, MapKind: for _, kvx := range cx.Elts { - un = findUndefinedGlobal(store, last, kvx.Key, nil) + un = findUndefinedV(store, last, kvx.Key, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedGlobal(store, last, kvx.Value, ct.Elem()) + un = findUndefinedV(store, last, kvx.Value, stack, defining, direct, ct.Elem()) if un != "" { return } } case StructKind: for _, kvx := range cx.Elts { - un = findUndefinedGlobal(store, last, kvx.Value, nil) + un = findUndefinedV(store, last, kvx.Value, stack, defining, direct, nil) if un != "" { return } @@ -4225,81 +3952,86 @@ func findUndefinedGlobal(store Store, last BlockNode, x Expr, t Type) (un Name) ct.String())) } case *FuncLitExpr: - for _, stmt := range cx.Body { - un = findUndefinedStmt(store, cx, stmt, t) - - if un != "" { - return - } + /* XXX delete + // TODO recursive preprocessing here is hacky, find a better + // way. This cannot be done asynchronously, cuz undefined + // names ought to be returned immediately to let the caller + // predefine it. + cx.Type = Preprocess(store, last, cx.Type).(Expr) // recursive + ct = evalStaticType(store, last, cx.Type) + */ + un = findUndefinedT(store, last, &cx.Type, stack, defining, direct) + if un != "" { + return } - return findUndefinedGlobal(store, last, &cx.Type, nil) - case *FieldTypeExpr: - return findUndefinedGlobal(store, last, cx.Type, nil) + cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + case *FieldTypeExpr: // FIELD + return findUndefinedT(store, last, cx.Type, stack, defining, direct) case *ArrayTypeExpr: if cx.Len != nil { - un = findUndefinedGlobal(store, last, cx.Len, nil) + un = findUndefinedV(store, last, cx.Len, stack, defining, direct, nil) if un != "" { return } } - return findUndefinedGlobal(store, last, cx.Elt, nil) + return findUndefinedT(store, last, cx.Elt, stack, defining, direct) case *SliceTypeExpr: - return findUndefinedGlobal(store, last, cx.Elt, nil) + return findUndefinedT(store, last, cx.Elt, stack, defining, false) case *InterfaceTypeExpr: for i := range cx.Methods { - un = findUndefinedGlobal(store, last, &cx.Methods[i], nil) + un = findUndefinedT(store, last, &cx.Methods[i], stack, defining, false) if un != "" { return } } case *ChanTypeExpr: - return findUndefinedGlobal(store, last, cx.Value, nil) + return findUndefinedT(store, last, cx.Value, stack, defining, false) case *FuncTypeExpr: for i := range cx.Params { - un = findUndefinedGlobal(store, last, &cx.Params[i], nil) + un = findUndefinedT(store, last, &cx.Params[i], stack, defining, false) if un != "" { return } } for i := range cx.Results { - un = findUndefinedGlobal(store, last, &cx.Results[i], nil) + un = findUndefinedT(store, last, &cx.Results[i], stack, defining, false) if un != "" { return } } case *MapTypeExpr: - un = findUndefinedGlobal(store, last, cx.Key, nil) + un = findUndefinedT(store, last, cx.Key, stack, defining, false) if un != "" { return } - un = findUndefinedGlobal(store, last, cx.Value, nil) + un = findUndefinedT(store, last, cx.Value, stack, defining, false) if un != "" { return } - case *StructTypeExpr: + case *StructTypeExpr: // STRUCT for i := range cx.Fields { - un = findUndefinedGlobal(store, last, &cx.Fields[i], nil) + un = findUndefinedT(store, last, &cx.Fields[i], stack, defining, direct) if un != "" { return } } case *CallExpr: - un = findUndefinedGlobal(store, last, cx.Func, nil) + un = findUndefinedV(store, last, cx.Func, stack, defining, direct, nil) if un != "" { return } for i := range cx.Args { - un = findUndefinedGlobal(store, last, cx.Args[i], nil) + un = findUndefinedV(store, last, cx.Args[i], stack, defining, direct, nil) if un != "" { return } } case *IndexExpr: - un = findUndefinedGlobal(store, last, cx.X, nil) + un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedGlobal(store, last, cx.Index, nil) + un = findUndefinedV(store, last, cx.Index, stack, defining, direct, nil) if un != "" { return } @@ -4315,219 +4047,13 @@ func findUndefinedGlobal(store Store, last BlockNode, x Expr, t Type) (un Name) return } -func findUndefined2(store Store, last BlockNode, x Expr, t Type, skipPredefined bool) (un Name) { - if x == nil { - return - } - switch cx := x.(type) { - case *NameExpr: - if tv := last.GetValueRef(store, cx.Name, skipPredefined); tv != nil { - return - } - if _, ok := UverseNode().GetLocalIndex(cx.Name); ok { - // XXX NOTE even if the name is shadowed by a file - // level declaration, it is fine to return here as it - // will be predefined later. - return - } - return cx.Name - case *BasicLitExpr: - return - case *BinaryExpr: - un = findUndefined2(store, last, cx.Left, nil, skipPredefined) - if un != "" { - return - } - un = findUndefined2(store, last, cx.Right, nil, skipPredefined) - if un != "" { - return - } - case *SelectorExpr: - return findUndefined2(store, last, cx.X, nil, skipPredefined) - case *SliceExpr: - un = findUndefined2(store, last, cx.X, nil, skipPredefined) - if un != "" { - return - } - if cx.Low != nil { - un = findUndefined2(store, last, cx.Low, nil, skipPredefined) - if un != "" { - return - } - } - if cx.High != nil { - un = findUndefined2(store, last, cx.High, nil, skipPredefined) - if un != "" { - return - } - } - if cx.Max != nil { - un = findUndefined2(store, last, cx.Max, nil, skipPredefined) - if un != "" { - return - } - } - case *StarExpr: - return findUndefined2(store, last, cx.X, nil, skipPredefined) - case *RefExpr: - return findUndefined2(store, last, cx.X, nil, skipPredefined) - case *TypeAssertExpr: - un = findUndefined2(store, last, cx.X, nil, skipPredefined) - if un != "" { - return - } - return findUndefined2(store, last, cx.Type, nil, skipPredefined) - case *UnaryExpr: - return findUndefined2(store, last, cx.X, nil, skipPredefined) - case *CompositeLitExpr: - var ct Type - if cx.Type == nil { - if t == nil { - panic("cannot elide unknown composite type") - } - ct = t - cx.Type = constType(cx, t) - } else { - un = findUndefined2(store, last, cx.Type, nil, skipPredefined) - if un != "" { - return - } - // preprocess now for eliding purposes. - // TODO recursive preprocessing here is hacky, find a better - // way. This cannot be done asynchronously, cuz undefined - // names ought to be returned immediately to let the caller - // predefine it. - cx.Type = Preprocess(store, last, cx.Type).(Expr) // recursive - ct = evalStaticType(store, last, cx.Type) - // elide composite lit element (nested) composite types. - elideCompositeElements(cx, ct) - } - switch ct.Kind() { - case ArrayKind, SliceKind, MapKind: - for _, kvx := range cx.Elts { - un = findUndefined2(store, last, kvx.Key, nil, skipPredefined) - if un != "" { - return - } - un = findUndefined2(store, last, kvx.Value, ct.Elem(), skipPredefined) - if un != "" { - return - } - } - case StructKind: - for _, kvx := range cx.Elts { - un = findUndefined2(store, last, kvx.Value, nil, skipPredefined) - if un != "" { - return - } - } - default: - panic(fmt.Sprintf( - "unexpected composite lit type %s", - ct.String())) - } - case *FuncLitExpr: - if cx.GetAttribute(ATTR_GLOBAL) == true { - for _, stmt := range cx.Body { - un = findUndefinedStmt(store, cx, stmt, t) - - if un != "" { - return - } - } - } - - return findUndefined2(store, last, &cx.Type, nil, skipPredefined) - case *FieldTypeExpr: - return findUndefined2(store, last, cx.Type, nil, skipPredefined) - case *ArrayTypeExpr: - if cx.Len != nil { - un = findUndefined2(store, last, cx.Len, nil, skipPredefined) - if un != "" { - return - } - } - return findUndefined2(store, last, cx.Elt, nil, skipPredefined) - case *SliceTypeExpr: - return findUndefined2(store, last, cx.Elt, nil, skipPredefined) - case *InterfaceTypeExpr: - for i := range cx.Methods { - un = findUndefined2(store, last, &cx.Methods[i], nil, skipPredefined) - if un != "" { - return - } - } - case *ChanTypeExpr: - return findUndefined2(store, last, cx.Value, nil, skipPredefined) - case *FuncTypeExpr: - for i := range cx.Params { - un = findUndefined2(store, last, &cx.Params[i], nil, skipPredefined) - if un != "" { - return - } - } - for i := range cx.Results { - un = findUndefined2(store, last, &cx.Results[i], nil, skipPredefined) - if un != "" { - return - } - } - case *MapTypeExpr: - un = findUndefined2(store, last, cx.Key, nil, skipPredefined) - if un != "" { - return - } - un = findUndefined(store, last, cx.Value) - if un != "" { - return - } - case *StructTypeExpr: - for i := range cx.Fields { - un = findUndefined2(store, last, &cx.Fields[i], nil, skipPredefined) - if un != "" { - return - } - } - case *CallExpr: - cx.Func.SetAttribute(ATTR_GLOBAL, cx.GetAttribute(ATTR_GLOBAL)) - un = findUndefined2(store, last, cx.Func, nil, skipPredefined) - if un != "" { - return - } - for i := range cx.Args { - un = findUndefined2(store, last, cx.Args[i], nil, skipPredefined) - if un != "" { - return - } - } - case *IndexExpr: - un = findUndefined2(store, last, cx.X, nil, skipPredefined) - if un != "" { - return - } - un = findUndefined2(store, last, cx.Index, nil, skipPredefined) - if un != "" { - return - } - case *constTypeExpr: - return - case *ConstExpr: - return - default: - panic(fmt.Sprintf( - "unexpected expr: %v (%v)", - x, reflect.TypeOf(x))) - } - return -} - -// like checkOrConvertType() but for any typed bool kind. -func checkOrConvertBoolKind(store Store, last BlockNode, n Node, x Expr) { - if cx, ok := x.(*ConstExpr); ok { - convertConst(store, last, n, cx, BoolType) - } else if x != nil { - xt := evalStaticTypeOf(store, last, x) - checkBoolKind(xt) +// like checkOrConvertType() but for any typed bool kind. +func checkOrConvertBoolKind(store Store, last BlockNode, n Node, x Expr) { + if cx, ok := x.(*ConstExpr); ok { + convertConst(store, last, n, cx, BoolType) + } else if x != nil { + xt := evalStaticTypeOf(store, last, x) + checkBoolKind(xt) } } @@ -4567,179 +4093,107 @@ func checkIntegerKind(xt Type) { } } -// predefineNow() pre-defines (with empty placeholders) all -// declaration names, and then preprocesses all type/value decls, and -// partially processes func decls. +// predefineRecursively() recursively defines or predefines (partially defines) +// all package level declaration names. *FuncDecl and *ValueDecl declarations +// are predefined (partially defined) while *ImportDecl and *TypeDecl are fully +// defined. // -// The recursive base procedure is split into two parts: +// It assumes that initStaticBlock has been called so that names are pre-reserved. // -// First, tryPredefine(), which first predefines with placeholder -// values/types to support recursive types, then returns yet -// un-predefined dependencies. +// It does NOT enter function bodies. // -// Second, which immediately preprocesses type/value declarations -// after dependencies have first been predefined, or partially -// preprocesses function declarations (which may not be completely -// preprocess-able before other file-level declarations are -// preprocessed). -func predefineNow(store Store, last BlockNode, d Decl) (Decl, bool) { +// This function works for all block nodes and is called for all declarations, +// but in two stages: in the first stage at the file level, and the second +// stage while preprocessing the body of each function. +// +// Returns true if the result was also preprocessed for *ImportDecl, *TypeDecl +// and *ValueDecl. *ValueDecl values are NOT evaluated at this stage. *FuncDecl +// are only partially defined and also only partially preprocessed. +func predefineRecursively(store Store, last BlockNode, d Decl) bool { defer doRecover([]BlockNode{last}, d) - stack := &[]Name{} - return predefineNow2(store, last, d, stack) + stack := []Name{} + defining := make(map[Name]struct{}) + return predefineRecursively2(store, last, d, stack, defining) } -func predefineNow2(store Store, last BlockNode, d Decl, stack *[]Name) (Decl, bool) { +// `stack` and `defining` are used for cycle detection. They hold the same data. +// NOTE: `stack` never truncates; a slice is used instead of a map to show a +// helpful message when a circular declaration is found. `defining` is also used as +// a map to ensure best time performance of circular definition detection. +func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}) bool { pkg := packageOf(last) - stackLen := len(*stack) - // pre-register d.GetName() to detect circular definition. + + // NOTE: predefine fileset breaks up circular definitions like + // `var a, b, c = 1, a, b` which is only legal at the file level. for _, dn := range d.GetDeclNames() { if isUverseName(dn) { panic(fmt.Sprintf( "builtin identifiers cannot be shadowed: %s", dn)) } - *stack = append(*stack, dn) - } - if stackLen != len(*stack) { - defer func() { - *stack = (*stack)[:stackLen] - }() - } - - // check type decl cycle - if td, ok := d.(*TypeDecl); ok { - // recursively check - assertTypeDeclNoCycle(store, last, td, stack) + stack = append(stack, dn) + defining[dn] = struct{}{} } + // After definition, remove items from map. + // The stack doesn't need to be truncated because + // the caller's stack slice remains the same regardless, + // but the defining map must remove predefined names, + // otherwise later declarations will fail. + defer func() { + for _, dn := range d.GetDeclNames() { + delete(defining, dn) + } + }() - // recursively predefine dependencies. + // recursively predefine any dependencies. for { - un := tryPredefine(store, pkg, last, d) + un := tryPredefine(store, pkg, last, d, stack, defining) if un != "" { // check circularity. - if slices.Contains(*stack, un) { + if _, exists := defining[un]; exists { + // XXX use stack to show the cycle. panic(fmt.Sprintf("constant definition loop with %s", un)) } // look up dependency declaration from fileset. - file, decl := pkg.FileSet.GetDeclFor(un) + file, unDecl := pkg.FileSet.GetDeclFor(un) // preprocess if not already preprocessed. if !file.IsInitialized() { panic("all types from files in file-set should have already been predefined") } - - declaration := *decl - declaration.SetAttribute(ATTR_GLOBAL, true) - - // predefine dependency (recursive). - *decl, _ = predefineNow2(store, file, declaration, stack) + // predefine dependency recursively. + predefineRecursively2(store, file, *unDecl, stack, defining) } else { - break + break // predefine successfully performed. } } switch cd := d.(type) { case *FuncDecl: - // *FuncValue/*FuncType is mostly empty still; here - // we just fill the func type (and recv if method). - // NOTE: unlike the *ValueDecl case, this case doesn't - // preprocess d itself (only d.Type). - if cd.IsMethod { - if cd.Recv.Name == "" || cd.Recv.Name == blankIdentifier { - panic("cd.Recv.Name should have been set in initStaticBlocks") - } - cd.Recv = *Preprocess(store, last, &cd.Recv).(*FieldTypeExpr) - cd.Type = *Preprocess(store, last, &cd.Type).(*FuncTypeExpr) - rft := evalStaticType(store, last, &cd.Recv).(FieldType) - rt := rft.Type - ft := evalStaticType(store, last, &cd.Type).(*FuncType) - ft = ft.UnboundType(rft) - dt := (*DeclaredType)(nil) - - // check base type of receiver type, should not be pointer type or interface type - assertValidReceiverType := func(t Type) { - if _, ok := t.(*PointerType); ok { - panic(fmt.Sprintf("invalid receiver type %v (base type is pointer type)", rt)) - } - if _, ok := t.(*InterfaceType); ok { - panic(fmt.Sprintf("invalid receiver type %v (base type is interface type)", rt)) - } - } - - if pt, ok := rt.(*PointerType); ok { - assertValidReceiverType(pt.Elem()) - if ddt, ok := pt.Elem().(*DeclaredType); ok { - assertValidReceiverType(baseOf(ddt)) - dt = ddt - } else { - panic("should not happen") - } - } else if ddt, ok := rt.(*DeclaredType); ok { - assertValidReceiverType(baseOf(ddt)) - dt = ddt - } else { - panic("should not happen") - } - // The body may get altered during preprocessing later. - if !dt.TryDefineMethod(&FuncValue{ - Type: ft, - IsMethod: true, - Source: cd, - Name: cd.Name, - Parent: nil, // set lazily - FileName: fileNameOf(last), - PkgPath: pkg.PkgPath, - Crossing: cd.Body.isCrossing(), - body: cd.Body, - nativeBody: nil, - }) { - // Revert to old function declarations in the package we're preprocessing. - pkg := packageOf(last) - pkg.StaticBlock.revertToOld() - panic(fmt.Sprintf("redeclaration of method %s.%s", - dt.Name, cd.Name)) - } - } else { - if cd.Name == "init" { - panic("cd.Name 'init' should have been appended with a number in initStaticBlocks") - } - ftv := pkg.GetValueRef(store, cd.Name, true) - ft := ftv.T.(*FuncType) - cd.Type = *Preprocess(store, last, &cd.Type).(*FuncTypeExpr) - ft2 := evalStaticType(store, last, &cd.Type).(*FuncType) - if !ft.IsZero() { - // redefining function. - // make sure the type is the same. - if ft.TypeID() != ft2.TypeID() { - panic(fmt.Sprintf( - "Redefinition (%s) cannot change .T; was %v, new %v", - cd, ft, ft2)) - } - // keep the orig type. - } else { - *ft = *ft2 - } - // XXX replace attr w/ ft? - // return Preprocess(store, last, cd).(Decl), true - } - // Full type declaration/preprocessing already done in tryPredefine - return d, false + // We cannot Preprocess the body of *FuncDecl as it may + // refer to package names in any order. + return false case *ValueDecl: - return Preprocess(store, last, cd).(Decl), true + vd2 := Preprocess(store, last, cd).(*ValueDecl) + *cd = *vd2 + return true case *TypeDecl: - return Preprocess(store, last, cd).(Decl), true + td2 := Preprocess(store, last, cd).(*TypeDecl) + *cd = *td2 + return true + case *ImportDecl: + id2 := Preprocess(store, last, cd).(*ImportDecl) + *cd = *id2 + return true default: - return d, false + panic("should not happen") } } -// If a dependent name is not yet defined, that name is -// returned; this return value is used by the caller to -// enforce declaration order. If a dependent type is not yet -// defined (preprocessed), that type is fully preprocessed. -// Besides defining the type (and immediate dependent types -// of d) onto last (or packageOf(last)), there are no other -// side effects. This function works for all block nodes and -// must be called for name declarations within (non-file, -// non-package) stmt bodies. -func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Name) { +// If a dependent name is not yet defined, that name is returned; this return +// value is used by the caller to enforce declaration order. +// +// If all dependencies are met, constructs and empty definition value (for a +// *TypeDecl is a TypeValue) and sets it on last. As an exception, *FuncDecls +// will preprocess receiver/argument/result types recursively. +func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}) (un Name) { if d.GetAttribute(ATTR_PREDEFINED) == true { panic(fmt.Sprintf("decl node already predefined! %v", d)) } @@ -4812,13 +4266,15 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Nam panic("cannot use _ as value or type") } - un = findUndefined(store, last, d.Type) + un = findUndefinedT(store, last, d.Type, stack, defining, false) // XXX if un != "" { return } + // NOTE: cyclic *ValueDecl at the package/file level such as + // `var a, b, c = 1, a, b` was already split up before reaching + // here, whereas they are illegal inside a function. for _, vx := range d.Values { - vx.SetAttribute(ATTR_GLOBAL, d.GetAttribute(ATTR_GLOBAL)) - un = findUndefined(store, last, vx) + un = findUndefinedV(store, last, vx, stack, defining, true, nil) if un != "" { return } @@ -4870,7 +4326,7 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Nam t = tv.GetType() if dt, ok := t.(*DeclaredType); ok { if !dt.sealed { - // predefineNow preprocessed dependent types. + // predefineRecursively preprocessed dependent types. panic("should not happen") } } @@ -4886,7 +4342,7 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Nam } case *SelectorExpr: // get package value. - un = findUndefined(store, last, tx.X) + un = findUndefinedV(store, last, tx.X, stack, defining, false, nil) if un != "" { return } @@ -4922,29 +4378,79 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Nam // last2.Define(d.Name, asValue(t)) last2.Define2(true, d.Name, t, asValue(t)) d.Path = last.GetPathForName(store, d.Name) - } + } // END *TypeDecl // after predefinitions, return any undefined dependencies. - un = findUndefined(store, last, d.Type) + un = findUndefinedT(store, last, d.Type, stack, defining, true) if un != "" { return } case *FuncDecl: - un = findUndefined(store, last, &d.Type) + un = findUndefinedT(store, last, &d.Type, stack, defining, false) if un != "" { return } if d.IsMethod { - // define method. - // methods are defined as struct fields, not - // in the last block. receiver isn't - // processed until FuncDecl:BLOCK. - un = findUndefined(store, last, &d.Recv) + un = findUndefinedT(store, last, &d.Recv, stack, defining, false) if un != "" { return } + if d.Recv.Name == "" || d.Recv.Name == blankIdentifier { + panic("d.Recv.Name should have been set in initStaticBlocks") + } + d.Recv = *Preprocess(store, last, &d.Recv).(*FieldTypeExpr) + d.Type = *Preprocess(store, last, &d.Type).(*FuncTypeExpr) + rft := evalStaticType(store, last, &d.Recv).(FieldType) + rt := rft.Type + ft := evalStaticType(store, last, &d.Type).(*FuncType) + ft = ft.UnboundType(rft) + dt := (*DeclaredType)(nil) + + // check base type of receiver type, should not be pointer type or interface type + assertValidReceiverType := func(t Type) { + if _, ok := t.(*PointerType); ok { + panic(fmt.Sprintf("invalid receiver type %v (base type is pointer type)", rt)) + } + if _, ok := t.(*InterfaceType); ok { + panic(fmt.Sprintf("invalid receiver type %v (base type is interface type)", rt)) + } + } + + if pt, ok := rt.(*PointerType); ok { + assertValidReceiverType(pt.Elem()) + if ddt, ok := pt.Elem().(*DeclaredType); ok { + assertValidReceiverType(baseOf(ddt)) + dt = ddt + } else { + panic("should not happen") + } + } else if ddt, ok := rt.(*DeclaredType); ok { + assertValidReceiverType(baseOf(ddt)) + dt = ddt + } else { + panic("should not happen") + } + // The body may get altered during preprocessing later. + if !dt.TryDefineMethod(&FuncValue{ + Type: ft, + IsMethod: true, + Source: d, + Name: d.Name, + Parent: nil, // set lazily + FileName: fileNameOf(last), + PkgPath: pkg.PkgPath, + Crossing: d.Body.isCrossing(), + body: d.Body, + nativeBody: nil, + }) { + // Revert to old function declarations in the package we're preprocessing. + pkg := packageOf(last) + pkg.StaticBlock.revertToOld() + panic(fmt.Sprintf("redeclaration of method %s.%s", + dt.Name, d.Name)) + } } else { if d.Name == "init" { - panic("cd.Name 'init' should have been appended with a number in initStaticBlocks") + panic("d.Name 'init' should have been appended with a number in initStaticBlocks") } // define package-level function. ft := &FuncType{} @@ -4973,15 +4479,35 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl) (un Nam fv.NativePkg = pkg.PkgPath fv.NativeName = d.Name } + // Set placeholder ft and fv. pkg.Define(d.Name, TypedValue{ T: ft, V: fv, }) + /* XXX delete if d.Name == "init" { // init functions can't be referenced. } else { d.Path = last.GetPathForName(store, d.Name) } + if d.Name == "init" { + panic("d.Name 'init' should have been appended with a number in initStaticBlocks") + } + */ + d.Type = *Preprocess(store, last, &d.Type).(*FuncTypeExpr) + ft2 := evalStaticType(store, last, &d.Type).(*FuncType) + if !ft.IsZero() { + // redefining function. + // make sure the type is the same. + if ft.TypeID() != ft2.TypeID() { + panic(fmt.Sprintf( + "Redefinition (%s) cannot change .T; was %v, new %v", + d, ft, ft2)) + } + // keep the orig type. + } else { + *ft = *ft2 + } } default: panic(fmt.Sprintf( @@ -5055,9 +4581,11 @@ func fillNameExprPath(last BlockNode, nx *NameExpr, isDefineLHS bool) { // If not DEFINE_LHS, yet is statically undefined, set path from parent. if !isDefineLHS { if last.GetStaticTypeOf(nil, nx.Name) == nil { - // NOTE: We cannot simply call last.GetPathForName() as below here, - // because .GetPathForName() doesn't distinguish between predefined - // and declared variables. See tests/files/define1.go for test case. + // NOTE: We cannot simply call last.GetPathForName() as + // below here, because .GetPathForName() doesn't + // distinguish between undefined reserved and and + // (pre)defined variables. See tests/files/define1.go + // for test case. var path ValuePath var i int = 0 var fauxChild int = 0 diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 41ed8ec1957..73a02705869 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -1265,6 +1265,8 @@ func copyValueWithRefs(val Value) Value { // fillTypes // (fully) fills the type. +// The store stores RefTypes, but this function fills it. +// This lets the store be independent of laziness. func fillType(store Store, typ Type) Type { switch ct := typ.(type) { case nil: diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 8df92f0d0e0..2f8b44ba643 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -405,7 +405,7 @@ func checkValDefineMismatch(n Node) { // 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(n Node, xt, dt Type, autoNative bool) error { +func checkAssignableTo(n Node, xt, dt Type, autoNative bool) (err error) { if debug { debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) } @@ -417,17 +417,17 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) error { if !maybeNil(dt) { switch n := n.(type) { case *ValueDecl: - panic(fmt.Sprintf("cannot use nil as %v value in variable declaration", dt)) + return errors.New("cannot use nil as %v value in variable declaration", dt) case *AssignStmt: - panic(fmt.Sprintf("cannot use nil as %v value in assignment", dt)) + return errors.New("cannot use nil as %v value in assignment", dt) case *CompositeLitExpr: - panic(fmt.Sprintf("cannot use nil as %v value in array, slice literal or map literal", dt)) + return errors.New("cannot use nil as %v value in array, slice literal or map literal", dt) case *CallExpr: - panic(fmt.Sprintf("cannot use nil as %v value in argument to %v", dt, n.Func)) + return errors.New("cannot use nil as %v value in argument to %v", dt, n.Func) case *BinaryExpr: - panic(fmt.Sprintf("invalid operation: %v (mismatched types %v and untyped nil)", n, dt)) + return errors.New("invalid operation: %v (mismatched types %v and untyped nil)", n, dt) default: - panic(fmt.Sprintf("cannot use nil as %v value", dt)) + return errors.New("cannot use nil as %v value", dt) } } return nil @@ -451,7 +451,7 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) error { err.Error()) } } else { - return errors.New("should not happen") + panic("should not happen") } } @@ -540,9 +540,9 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) error { Uint32Kind, Uint64Kind, BigdecKind, Float32Kind, Float64Kind: return nil // ok default: - panic(fmt.Sprintf( + return errors.New( "cannot use untyped Bigdec as %s", - dt.Kind())) + dt.Kind()) } case UntypedBigintType: switch dt.Kind() { @@ -569,7 +569,7 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) error { default: if isUntyped(xt) { - panic("unexpected untyped type") + return errors.New("unexpected untyped type") } if xt.TypeID() == cdt.TypeID() { return nil // ok @@ -623,7 +623,7 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) error { return nil } case *InterfaceType: - return errors.New("should not happen") + panic("should not happen") case *DeclaredType: panic("should not happen") case *FuncType, *StructType, *PackageType, *ChanType, *TypeType: @@ -721,9 +721,9 @@ func (x *BinaryExpr) assertShiftExprCompatible2(t Type) { // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. func (x *BinaryExpr) AssertCompatible(lt, rt Type) { - xt, dt := lt, rt + xt, dt, swapped := lt, rt, false if shouldSwapOnSpecificity(lt, rt) { - xt, dt = dt, xt + xt, dt, swapped = dt, xt, true } if isComparison(x.Op) { @@ -735,7 +735,7 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { } case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[x.Op]; ok { - x.checkCompatibility(x, xt, dt, checker, x.Op.TokenString()) + x.checkCompatibility(x, xt, dt, checker, x.Op.TokenString(), swapped) } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } @@ -744,7 +744,7 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { } } else { if checker, ok := binaryChecker[x.Op]; ok { - x.checkCompatibility(x, xt, dt, checker, x.Op.TokenString()) + x.checkCompatibility(x, xt, dt, checker, x.Op.TokenString(), swapped) } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } @@ -772,16 +772,29 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { // 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(n Node, xt, dt Type, checker func(t Type) bool, OpStr string) { +func (x *BinaryExpr) checkCompatibility(n Node, xt, dt Type, checker func(t Type) bool, OpStr string, swapped bool) { if !checker(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(dt))) } + // display xt as "untyped nil" if nil as Go does. + var untypedNil = func(t Type) string { + if t == nil { + return "untyped nil" + } else { + return t.String() + } + } + // if both typed if !isUntyped(xt) && !isUntyped(dt) { err := checkAssignableTo(n, xt, dt, false) if err != nil { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", xt, dt)) + if swapped { + panic(fmt.Sprintf("invalid operation: %v (mismatched types %v and %v)", n, dt, untypedNil(xt))) + } else { + panic(fmt.Sprintf("invalid operation: %v (mismatched types %v and %v)", n, untypedNil(xt), dt)) + } } } } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index c102c033aeb..f233fe80de8 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1269,16 +1269,9 @@ func (ft *FuncType) TypeID() TypeID { // this exchangeability is useful to denote type semantics. ps := FieldTypeList(ft.Params) rs := FieldTypeList(ft.Results) - /* - pp := "" - if ps.HasUnexported() || rs.HasUnexported() { - pp = fmt.Sprintf("@%q", ft.PkgPath) - } - */ if ft.typeid.IsZero() { ft.typeid = typeidf( "func(%s)(%s)", - // pp, ps.UnnamedTypeID(), rs.UnnamedTypeID(), ) @@ -1289,12 +1282,15 @@ func (ft *FuncType) TypeID() TypeID { func (ft *FuncType) String() string { switch len(ft.Results) { case 0: + // XXX add ->() return fmt.Sprintf("func(%s)", FieldTypeList(ft.Params).StringForFunc()) case 1: + // XXX add ->() return fmt.Sprintf("func(%s) %s", FieldTypeList(ft.Params).StringForFunc(), ft.Results[0].Type.String()) default: + // XXX make ()->() return fmt.Sprintf("func(%s) (%s)", FieldTypeList(ft.Params).StringForFunc(), FieldTypeList(ft.Results).StringForFunc()) @@ -1484,6 +1480,11 @@ func (dt *DeclaredType) checkSeal() { func (dt *DeclaredType) TypeID() TypeID { if dt.typeid.IsZero() { dt.typeid = DeclaredTypeID(dt.PkgPath, dt.Loc, dt.Name) + } else { + // XXX delete this if tests pass. + if dt.typeid != DeclaredTypeID(dt.PkgPath, dt.Loc, dt.Name) { + panic("should not happen") + } } return dt.typeid } diff --git a/gnovm/stdlibs/crypto/bech32/bech32_test.gno b/gnovm/stdlibs/crypto/bech32/bech32_test.gno index 3f637c40345..9525323403a 100644 --- a/gnovm/stdlibs/crypto/bech32/bech32_test.gno +++ b/gnovm/stdlibs/crypto/bech32/bech32_test.gno @@ -10,7 +10,7 @@ import ( "encoding/hex" "fmt" "strings" - "testing" + testing "testing/base" ) // TestBech32 tests whether decoding and re-encoding the valid BIP-173 test diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index 53206675e74..a9d27d9a303 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -14,6 +14,7 @@ import ( libs_std "github.com/gnolang/gno/gnovm/stdlibs/std" libs_sys_params "github.com/gnolang/gno/gnovm/stdlibs/sys/params" libs_testing "github.com/gnolang/gno/gnovm/stdlibs/testing" + libs_testing_base "github.com/gnolang/gno/gnovm/stdlibs/testing/base" libs_time "github.com/gnolang/gno/gnovm/stdlibs/time" ) @@ -1214,6 +1215,86 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "testing/base", + "unixNano", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("int64")}, + }, + false, + func(m *gno.Machine) { + r0 := libs_testing_base.X_unixNano() + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + }, + }, + { + "testing/base", + "recoverWithStacktrace", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.AnyT()}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + false, + func(m *gno.Machine) { + r0, r1 := libs_testing_base.X_recoverWithStacktrace() + + m.PushValue(r0) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, + { + "testing/base", + "matchString", + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("p0"), Type: gno.X("string")}, + {NameExpr: *gno.Nx("p1"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("bool")}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + false, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() + ) + + tv0 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV + tv0.DeepFill(m.Store) + gno.Gno2GoValue(tv0, rp0) + tv1 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV + tv1.DeepFill(m.Store) + gno.Gno2GoValue(tv1, rp1) + + r0, r1 := libs_testing_base.X_matchString(p0, p1) + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, { "time", "now", @@ -1324,6 +1405,7 @@ var initOrder = [...]string{ "sys/params", "time", "testing", + "testing/base", "unicode/utf16", } diff --git a/gnovm/stdlibs/testing/base/fuzz.gno b/gnovm/stdlibs/testing/base/fuzz.gno new file mode 100644 index 00000000000..1022f2961d6 --- /dev/null +++ b/gnovm/stdlibs/testing/base/fuzz.gno @@ -0,0 +1,284 @@ +package base + +import "strings" + +type Fuzzer interface { + InsertDeleteMutate(p float64) Fuzzer + Mutate() Fuzzer + String() string +} + +type StringFuzzer struct { + Value string + f *F +} + +func NewStringFuzzer(value string) *StringFuzzer { + return &StringFuzzer{Value: value} +} + +// Mutate changes a StringFuzzer's value by replacing a random character +// with a random ASCII character. +func (sf *StringFuzzer) Mutate() Fuzzer { + runes := []rune(sf.Value) + if len(runes) == 0 { + return sf + } + + index := randRange(0, len(runes)-1) + runes[index] = randomASCIIChar() + + return NewStringFuzzer(string(runes)) +} + +func (sf *StringFuzzer) InsertDeleteMutate(p float64) Fuzzer { + value := InsertDelete(sf.Value, p) + return NewStringFuzzer(value) +} + +func (sf *StringFuzzer) Fuzz() string { + if GenerateRandomBool(0.2) { + return InsertDelete(sf.Value, 0.1) + } + + rs := []rune(sf.Value) + lrs := len(rs) + + if lrs == 0 { + return sf.Value + } + + index := randRange(0, lrs-1) + rs[index] = randomASCIIChar() + + return string(rs) +} + +func (sf *StringFuzzer) String() string { + return sf.Value +} + +func randomASCIIChar() rune { + r := int(randRange(32, 126)) + + return rune(r) +} + +// Individual represents a single individual in the population. +type Individual struct { + Fuzzer Fuzzer + Fitness int +} + +func NewIndividual(fuzzer Fuzzer) *Individual { + return &Individual{Fuzzer: fuzzer} +} + +func (ind *Individual) calculateFitness() { + ind.Fitness = len(ind.Fuzzer.String()) +} + +// Selection selects individuals from the population based on their fitness. +// +// Use roulette wheel selection to select individuals from the population. +// ref: https://en.wikipedia.org/wiki/Fitness_proportionate_selection +func Selection(population []*Individual) []*Individual { + totalFitness := calculateTotalFitness(population) + selected := make([]*Individual, len(population)) + + for i := range selected { + selected[i] = selectIndividual(population, totalFitness) + } + + return selected +} + +func calculateTotalFitness(population []*Individual) int { + totalFitness := 0 + + for _, ind := range population { + totalFitness += ind.Fitness + } + + return totalFitness +} + +func selectIndividual(population []*Individual, totalFitness int) *Individual { + pick := randRange(0, totalFitness-1) + sum := 0 + + for _, ind := range population { + sum += ind.Fitness + if uint64(sum) > uint64(pick) { + return ind + } + } + + return nil +} + +// Crossover takes two parents and creates two children by combining their genetic material. +// +// The pivot point is chosen randomly from the length of the shortest parent. after the pivot point selected, +// the genetic material of the two parents is swapped to create the two children. +func Crossover(parent1, parent2 *Individual) (*Individual, *Individual) { + p1Runes := []rune(parent1.Fuzzer.String()) + p2Runes := []rune(parent2.Fuzzer.String()) + + p1Len := len(p1Runes) + p2Len := len(p2Runes) + + point := 0 + if p1Len >= p2Len { + point = int(randRange(0, p2Len-1)) + } else { + point = int(randRange(0, p1Len-1)) + } + + child1 := append(append([]rune{}, p1Runes[:point]...), p2Runes[point:]...) + child2 := append(append([]rune{}, p2Runes[:point]...), p1Runes[point:]...) + + updatedIdv1 := NewIndividual(NewStringFuzzer(string(child1))) + updatedIdv2 := NewIndividual(NewStringFuzzer(string(child2))) + + return updatedIdv1, updatedIdv2 +} + +func (ind *Individual) Mutate() { + ind.Fuzzer = ind.Fuzzer.Mutate() +} + +// InsertDelete randomly inserts or deletes a character from a string. +func InsertDelete(s string, p float64) string { + rr := []rune(s) + l := len(rr) + + // Insert + if GenerateRandomBool(p) { + pos := randRange(0, l-1) + rr = append(rr, 0) + + copy(rr[pos+1:], rr[pos:]) + + char := randomASCIIChar() + rr[pos] = char + } else { + if l == 0 { + return s + } + + pos := randRange(0, l-1) + rr = append(rr[:pos], rr[pos+1:]...) + } + + return string(rr) +} + +type F struct { + corpus []string + failed bool // Indicates whether the fuzzing has encountered a failure. + msgs []string // Stores log messages for reporting. + iters int // Number of iterations to run the fuzzing process. TODO: CLI flag to set this. +} + +// Runner is a type for the target function to fuzz. +type Runner func(*T, ...any) + +// Fuzz applies the fuzzing process to the target function. +func (f *F) Fuzz(run Runner, iter int) { + f.evolve(iter) + + for _, input := range f.corpus { + args := make([]any, len(f.corpus)) + for i := range args { + args[i] = input + } + + run(nil, args...) + } +} + +// Add adds test values to initialize the corpus. +func (f *F) Add(values ...any) []Fuzzer { + fuzzers := make([]Fuzzer, len(values)) + + for i, v := range values { + str, ok := v.(string) + if !ok { + continue + } + f.corpus = append(f.corpus, str) + fuzzers[i] = &StringFuzzer{Value: str} + } + + return fuzzers +} + +func (f *F) evolve(generations int) { + population := make([]*Individual, len(f.corpus)) + for i, c := range f.corpus { + population[i] = &Individual{Fuzzer: &StringFuzzer{Value: c, f: f}} + } + + for _, ind := range population { + ind.calculateFitness() + } + + for gen := 0; gen < generations; gen++ { + population = Selection(population) + newPopulation := make([]*Individual, 0, len(population)) + + for i := 0; i < len(population); i += 2 { + if i+1 < len(population) { + child1, child2 := Crossover(population[i], population[i+1]) + newPopulation = append(newPopulation, child1, child2) + continue + } + + newPopulation = append(newPopulation, population[i]) + } + + var bestFitness int + + for _, ind := range newPopulation { + if GenerateRandomBool(0.2) { + ind.Mutate() + } + + if GenerateRandomBool(0.1) { + ind.Fuzzer = ind.Fuzzer.InsertDeleteMutate(0.3) + } + + ind.calculateFitness() + + if ind.Fitness > bestFitness { + bestFitness = ind.Fitness + } + } + + population = newPopulation + } + + f.corpus = make([]string, len(population)) + for i, ind := range population { + f.corpus[i] = ind.Fuzzer.String() + } +} + +// Fail marks the function as having failed bur continue execution. +func (f *F) Fail() { + f.failed = true +} + +// Fatal is equivalent to Log followed by FailNow. +// It logs the message and marks the fuzzing as failed. +func (f *F) Fatal(args ...any) { + var sb strings.Builder + + for _, arg := range args { + sb.WriteString(arg.(string)) + } + + f.msgs = append(f.msgs, sb.String()) + f.Fail() +} diff --git a/gnovm/stdlibs/testing/base/fuzz_test.gno b/gnovm/stdlibs/testing/base/fuzz_test.gno new file mode 100644 index 00000000000..6464b0d6d38 --- /dev/null +++ b/gnovm/stdlibs/testing/base/fuzz_test.gno @@ -0,0 +1,168 @@ +package base + +import "strings" + +func TestMutate(t *T) { + originalValue := "Hello" + fuzzer := StringFuzzer{Value: originalValue} + + newFuzzer := fuzzer.Mutate().(*StringFuzzer) + + if newFuzzer.Value == originalValue { + t.Errorf("Mutate did not change the string: got %v, want different from %v", newFuzzer.Value, originalValue) + } + + if len(newFuzzer.Value) != len(originalValue) { + t.Errorf("Mutated string has different length: got %s (len=%v), want %s (len=%v)", newFuzzer.Value, len(newFuzzer.Value), originalValue, len(originalValue)) + } +} + +func TestSelection(t *T) { + tests := []struct { + name string + population []*Individual + }{ + { + name: "Empty population", + population: []*Individual{}, + }, + { + name: "Uniform fitness", + population: []*Individual{ + {Fitness: 10}, + {Fitness: 10}, + {Fitness: 10}, + }, + }, + { + name: "Different fitness", + population: []*Individual{ + {Fitness: 5}, + {Fitness: 15}, + {Fitness: 10}, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *T) { + selected := Selection(tc.population) + if len(selected) != len(tc.population) { + t.Errorf("Expected selected length to be %d, got %d", len(tc.population), len(selected)) + } + }) + } +} + +func TestCrossover(t *T) { + parent1 := NewIndividual(&StringFuzzer{Value: "foobar"}) + parent2 := NewIndividual(&StringFuzzer{Value: "bazbiz"}) + + var child1, child2 *Individual + for i := 0; i < 100; i++ { + child1, child2 = Crossover(parent1, parent2) + } + + if child1.Fuzzer.String() == "foobar" || child2.Fuzzer.String() == "bazbiz" { + t.Errorf("Crossover did not modify children correctly, got %s and %s", child1.Fuzzer.String(), child2.Fuzzer.String()) + } +} + +func Test_StringManipulation(t *T) { + f := &F{ + corpus: []string{"hello", "world", "foo", "bar"}, + } + + f.evolve(30) + + if len(f.corpus) != 4 { + t.Fatalf("corpus length is %d, want 4", len(f.corpus)) + } + + for i, c := range f.corpus { + if c == "" { + t.Fatalf("corpus[%d] is empty", i) + } + + if len(c) < 3 { + t.Fatalf("corpus[%d] is too short: %s", i, c) + } + + if f.corpus[0] == "hello" { + t.Fatalf("corpus[0] is still the same: %s", f.corpus[0]) + } + + if f.corpus[1] == "world" { + t.Fatalf("corpus[1] is still the same: %s", f.corpus[1]) + } + + if f.corpus[2] == "foo" { + t.Fatalf("corpus[2] is still the same: %s", f.corpus[2]) + } + + if f.corpus[3] == "bar" { + t.Fatalf("corpus[3] is still the same: %s", f.corpus[3]) + } + + } +} + +func TestFuzz(t *T) { + f := F{} + f.Add("hello", "world", "foo") + f.Fuzz(func(t *T, inputs ...any) { + for _, input := range inputs { + strInput, ok := input.(string) + if !ok { + t.Errorf("Type mismatch, expected a string but got %T", input) + continue + } + + words := strings.Fields(strInput) + if len(words) == 0 { + t.Errorf("Expected non-empty input") + } + } + }, 15) + + if len(f.corpus) == 0 { + t.Fatalf("Fuzzing corpus is empty after testing") + } + + if len(f.corpus) > 3 { + t.Fatalf("Fuzzing corpus has more than 3 elements: %v", f.corpus) + } + + for _, c := range f.corpus { + if c == "hello" || c == "world" || c == "foo" { + t.Fatalf("Fuzzing corpus still contains the original elements: %v", f.corpus) + } + } +} + +func TestF_Fail(t *T) { + f := F{} + f.Fail() + + if !f.failed { + t.Errorf("Fail did not set the failed flag.") + } +} + +func TestF_Fatal(t *T) { + f := F{} + testMessage := "test failure message" + f.Fatal(testMessage) + + if !f.failed { + t.Errorf("Fatal did not set the failed flag.") + } + + if len(f.msgs) != 1 { + t.Fatalf("Fatal did not set the message correctly: got %v, want %v", f.msgs, testMessage) + } + + if !strings.Contains(f.msgs[0], testMessage) { + t.Errorf("Fatal did not set the message correctly: got %v, want %v", f.msgs[0], testMessage) + } +} diff --git a/gnovm/stdlibs/testing/base/match.gno b/gnovm/stdlibs/testing/base/match.gno new file mode 100644 index 00000000000..25d1da808c0 --- /dev/null +++ b/gnovm/stdlibs/testing/base/match.gno @@ -0,0 +1,165 @@ +package base + +// Most of the code in this file is extracted from golang's src/testing/match.go. +// +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +import ( + "fmt" + "strings" + "unicode" +) + +type filterMatch interface { + // matches checks the name against the receiver's pattern strings using the + // given match function. + matches(name []string) (ok, partial bool) + + // verify checks that the receiver's pattern strings are valid filters by + // calling the given match function. + verify(name string) error +} + +// simpleMatch matches a test name if all of the pattern strings match in +// sequence. +type simpleMatch []string + +// alternationMatch matches a test name if one of the alternations match. +type alternationMatch []filterMatch + +func (m simpleMatch) matches(name []string) (ok, partial bool) { + for i, s := range name { + if i >= len(m) { + break + } + if ok, _ := matchString(m[i], s); !ok { + return false, false + } + } + return true, len(name) < len(m) +} + +func (m simpleMatch) verify(name string) error { + for i, s := range m { + m[i] = rewrite(s) + } + // Verify filters before doing any processing. + for i, s := range m { + if _, err := matchString(s, "non-empty"); err != "" { + return fmt.Errorf("element %d of %s (%q): %s", i, name, s, err) + } + } + return nil +} + +func (m alternationMatch) matches(name []string) (ok, partial bool) { + for _, m := range m { + if ok, partial = m.matches(name); ok { + return ok, partial + } + } + return false, false +} + +func (m alternationMatch) verify(name string) error { + for i, m := range m { + if err := m.verify(name); err != nil { + return fmt.Errorf("alternation %d of %s", i, err) + } + } + return nil +} + +func splitRegexp(s string) filterMatch { + a := make(simpleMatch, 0, strings.Count(s, "/")) + b := make(alternationMatch, 0, strings.Count(s, "|")) + cs := 0 + cp := 0 + for i := 0; i < len(s); { + switch s[i] { + case '[': + cs++ + case ']': + if cs--; cs < 0 { // An unmatched ']' is legal. + cs = 0 + } + case '(': + if cs == 0 { + cp++ + } + case ')': + if cs == 0 { + cp-- + } + case '\\': + i++ + case '/': + if cs == 0 && cp == 0 { + a = append(a, s[:i]) + s = s[i+1:] + i = 0 + continue + } + case '|': + if cs == 0 && cp == 0 { + a = append(a, s[:i]) + s = s[i+1:] + i = 0 + b = append(b, a) + a = make(simpleMatch, 0, len(a)) + continue + } + } + i++ + } + + a = append(a, s) + if len(b) == 0 { + return a + } + return append(b, a) +} + +// rewrite rewrites a subname to having only printable characters and no white +// space. +func rewrite(s string) string { + b := []byte{} + for _, r := range s { + switch { + case isSpace(r): + b = append(b, '_') + case !unicode.IsPrint(r): + s := simpleQuoteRune(r) + b = append(b, s[1:len(s)-1]...) + default: + b = append(b, string(r)...) + } + } + return string(b) +} + +// simpleQuoteRune does not follow the original strconv.QuoteRune. +func simpleQuoteRune(r rune) string { + return "." +} + +func isSpace(r rune) bool { + if r < 0x2000 { + switch r { + // Note: not the same as Unicode Z class. + case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0, 0x1680: + return true + } + } else { + if r <= 0x200a { + return true + } + switch r { + case 0x2028, 0x2029, 0x202f, 0x205f, 0x3000: + return true + } + } + return false +} diff --git a/gnovm/stdlibs/testing/base/random.gno b/gnovm/stdlibs/testing/base/random.gno new file mode 100644 index 00000000000..8e46a6ab0f7 --- /dev/null +++ b/gnovm/stdlibs/testing/base/random.gno @@ -0,0 +1,72 @@ +package base + +import "math" + +// Internal state for the random number generator. +var x uint64 = 42 + +// UniformRand generates a uniformly distributed random number. +// It uses the linear congrential generator method to produce the random number. +// and the result is in the range from 0 to m-1. here, m is 32768. +// To produce random number in [0, m-1], repeat this method as many times as needed. +// [1] https://en.wikipedia.org/wiki/Linear_congruential_generator +func UniformRand() uint64 { + var a uint64 = 950213 + var c uint64 = 12345 + var m uint64 = 32768 + x = x*a + c + return (x >> 16) % m +} + +// _srand function sets the seed for the random number generator. +// This function provides an initial starting point for the sequence of random numbers. +func _srand(seed int64) { + x = uint64(seed) +} + +// nrand function generates a number approximating a normal distribution[1]. +// It uses the Central Limit Theorem[2] by summing multiple uniformly distributed random numbers +// to approximate a normal distribution. +// +// y = Sum(k=1, K) (x_k - K/2) / sqrt(K/12) +// +// Here, K is some integer ans x_k are uniformly distributed numbers, +// even for K as small as 10, the approximation is quite good. +// [1] https://en.wikipedia.org/wiki/Normal_distribution +// [2] https://en.wikipedia.org/wiki/Central_limit_theorem +func nrand() float64 { + var i, K uint64 = 0, 10 + var m uint64 = 32768 + var y float64 = 0 + + for i = 0; i < K; i++ { + y += float64(UniformRand()) / float64(m) + } + y = (y - float64(K)/2) / math.Sqrt(float64(K)/12) + return y +} + +// randRange generates a random integer between min and max (inclusive). +// This function leverages the UniformRand function to generate a random number in a specified range. +// Note: max should be greater than min. +func randRange(min, max int) uint64 { + _min := uint64(min) + _max := uint64(max) + if _min >= _max { + return _min + } + + rangeSize := _max - _min + 1 + // adjust UniformRand to fit into our range. + return _min + (UniformRand() % rangeSize) +} + +func GenerateRandomBool(bias float64) bool { + // Modify to use fuzz's random function for generating boolean with bias + if bias < 0 || bias > 1 { + panic("bias should be in the range [0, 1]") + } + // Convert fuzz's normalized range random float [-1, 1] to [0, 1] + res := (nrand() + 1) / 2 + return res > bias +} diff --git a/gnovm/stdlibs/testing/base/random_test.gno b/gnovm/stdlibs/testing/base/random_test.gno new file mode 100644 index 00000000000..bdb4948a13c --- /dev/null +++ b/gnovm/stdlibs/testing/base/random_test.gno @@ -0,0 +1,98 @@ +package base + +import ( + "math" + "time" +) + +func updateSeed() { + seed := time.Now().UnixNano() + _srand(seed) +} + +func Test_UniformRand(t *T) { + valueMap := make(map[uint64]int) + maxIter := 1000 + + for i := 0; i < maxIter; i++ { + result := UniformRand() + + if result < 0 || result >= 32768 { + t.Errorf("rand() = %v, want in range [0, 32767]", result) + } + + if _, ok := valueMap[result]; ok { + valueMap[result]++ + } else { + valueMap[result] = 1 + } + } + + lvm := len(valueMap) + if lvm > maxIter || lvm == 0 { + t.Errorf("len(valueMap) = %v, want <= %v", lvm, maxIter) + } +} + +func Test_nrand(t *T) { + sum := 0.0 + for i := 0; i < 1000; i++ { + result := nrand() + sum += result + } + avg := sum / float64(1000) + + // The value returned by nrand() should be close to 0 + // on average for large sample sizes. + // The expectation of the standard deviation should be + // close to 1 for large sample sizes. + if math.Abs(avg) > 0.1 { // can be adjusted based on sample size + t.Errorf("nrand() = %v, want in range [-0.1, 0.1]", avg) + } +} + +func Test_GenerateRandomBool(t *T) { + updateSeed() + + for _, bias := range []float64{0, 0.5, 1} { + trueCount, falseCount := 0, 0 + sampleSize := 1000 + + for i := 0; i < sampleSize; i++ { + result := GenerateRandomBool(bias) + if result { + trueCount++ + } else { + falseCount++ + } + } + + if trueCount == 0 || falseCount == 0 { + t.Errorf("Bias = %v, trueCount = %v, falseCount = %v, want both > 0", bias, trueCount, falseCount) + } + + if bias < 0 || bias > 1 { + t.Errorf("Bias = %v, want in range [0, 1]", bias) + } + } +} + +func TestRandRange(t *T) { + nums := make(map[uint64]int) + for i := 0; i < 1000; i++ { + res := randRange(0, 10) + if res < 0 || res > 10 { + t.Errorf("gerandRangenerateRange() = %v, want in range [0, 9]", res) + } + + if _, ok := nums[res]; ok { + nums[res]++ + } else { + nums[res] = 1 + } + } + + if len(nums) != 11 { + t.Errorf("len(nums) = %v, want in range [0, 10]", len(nums)) + } +} diff --git a/gnovm/stdlibs/testing/base/testing.gno b/gnovm/stdlibs/testing/base/testing.gno new file mode 100644 index 00000000000..7466af1fce2 --- /dev/null +++ b/gnovm/stdlibs/testing/base/testing.gno @@ -0,0 +1,384 @@ +// Shim for Go's "testing" package to support minimal testing types. +package base + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +// ---------------------------------------- +// Top level functions + +// SkipErr is the type of the panic created by SkipNow +// and FailNow. Having it as a simple string means that it can be fmt.Printf'd +// easily (and doesn't get "corrupted" through gno2go). +type SkipErr string + +func (s SkipErr) Error() string { + return string(s) +} + +// Recover functions like recover(), but it ensures that the recovered error is +// not an internal error of the testing package. +// +// Due to a lack of goroutines and thus runtime.Goexit, gno's testing system resorts +// to panics to abort testing with FailNow (and Fatal* functions) or SkipNow +// (and Skip* functions). +// +// NOTE: Recover() is likely to be removed. +func Recover(result Setter) { + r := recover() + if _, ok := r.(SkipErr); !ok { + result.Set(r) + return + } + + panic(r) +} + +type Setter interface { + Set(v any) +} + +func Short() bool { + return true // TODO configure somehow. +} + +func Verbose() bool { + return true // TODO configure somehow. +} + +// Like AllocsPerRun() but returns an integer. +// TODO: actually compute allocations; for now return 0. +func AllocsPerRun2(runs int, f func()) (total int) { + for i := 0; i < runs; i++ { + f() + } + return 0 +} + +// ---------------------------------------- +// T + +type T struct { + name string + failed bool + skipped bool + subs []*T + parent *T + output []byte // Output generated by test + verbose bool + failfast bool + runFilter filterMatch + dur string +} + +func NewT(name string) *T { + return &T{name: name} +} + +type testingFunc func(*T) + +// Not yet implemented: +// func (t *T) Cleanup(f func()) { +// func (t *T) Deadline() (deadline time.Time, ok bool) +func (t *T) Error(args ...any) { + t.Log(args...) + t.Fail() +} + +func (t *T) Errorf(format string, args ...any) { + t.Logf(format, args...) + t.Fail() +} + +func (t *T) Fail() { + t.failed = true +} + +func (t *T) FailNow() { + t.Fail() + panic(SkipErr("testing: you have recovered a panic attempting to interrupt a test, as a consequence of FailNow. " + + "Use testing.Recover to recover panics within tests")) +} + +func (t *T) Failed() bool { + if t.failed { + return true + } + for _, sub := range t.subs { + if sub.Failed() { + return true + } + } + return false +} + +// only called when verbose == false +func (t *T) printFailure() { + fmt.Fprintf(os.Stderr, "--- FAIL: %s (%s)\n", t.name, t.dur) + if t.failed { + fmt.Fprint(os.Stderr, string(t.output)) + } + for _, sub := range t.subs { + if sub.Failed() { + sub.printFailure() + } + } +} + +func (t *T) Fatal(args ...any) { + t.Log(args...) + t.FailNow() +} + +func (t *T) Fatalf(format string, args ...any) { + t.Logf(format, args...) + t.FailNow() +} + +func (t *T) Log(args ...any) { + t.log(fmt.Sprintln(args...)) +} + +func (t *T) Logf(format string, args ...any) { + t.log(fmt.Sprintf(format, args...)) + t.log(fmt.Sprintln()) +} + +func (t *T) Name() string { + return t.name +} + +func (t *T) Parallel() { + // does nothing. +} + +func (t *T) Run(name string, f testingFunc) bool { + fullName := t.name + "/" + rewrite(name) + + subT := &T{ + parent: t, + name: fullName, + verbose: t.verbose, + runFilter: t.runFilter, + } + + if t.failfast && t.Failed() { + return false + } + + t.subs = append(t.subs, subT) + + tRunner(subT, f, t.verbose) + return true +} + +func (t *T) Setenv(key, value string) { + panic("not yet implemented") +} + +func (t *T) Skip(args ...any) { + t.Log(args...) + t.SkipNow() +} + +func (t *T) SkipNow() { + t.skipped = true + panic(SkipErr("testing: you have recovered a panic attempting to interrupt a test, as a consequence of SkipNow. " + + "Use testing.Recover to recover panics within tests")) +} + +func (t *T) Skipped() bool { + return t.skipped +} + +func (t *T) Skipf(format string, args ...any) { + t.Logf(format, args...) + t.SkipNow() +} + +func (t *T) TempDir() string { + panic("not yet implemented") +} + +func (t *T) Helper() { +} + +func (t *T) log(s string) { + if t.verbose { + // verbose, print immediately + fmt.Fprint(os.Stderr, s) + } else { + // defer printing only if test is failed + t.output = append(t.output, s...) + } +} + +type Report struct { + Failed bool + Skipped bool +} + +func (r *Report) marshal() string { + failed := "false" + skipped := "false" + if r.Failed { + failed = "true" + } + if r.Skipped { + skipped = "true" + } + return `{"Failed":` + failed + `,"Skipped":` + skipped + `}` +} + +func (t *T) report() Report { + return Report{ + Failed: t.Failed(), + Skipped: t.skipped, + } +} + +// ---------------------------------------- +// B +// TODO: actually implement + +type B struct { + N int +} + +func (b *B) Cleanup(f func()) { panic("not yet implemented") } +func (b *B) Error(args ...any) { panic("not yet implemented") } +func (b *B) Errorf(format string, args ...any) { panic("not yet implemented") } +func (b *B) Fail() { panic("not yet implemented") } +func (b *B) FailNow() { panic("not yet implemented") } +func (b *B) Failed() bool { panic("not yet implemented") } +func (b *B) Fatal(args ...any) { panic("not yet implemented") } +func (b *B) Fatalf(format string, args ...any) { panic("not yet implemented") } +func (b *B) Helper() { panic("not yet implemented") } +func (b *B) Log(args ...any) { panic("not yet implemented") } +func (b *B) Logf(format string, args ...any) { panic("not yet implemented") } +func (b *B) Name() string { panic("not yet implemented") } +func (b *B) ReportAllocs() { panic("not yet implemented") } +func (b *B) ReportMetric(n float64, unit string) { panic("not yet implemented") } +func (b *B) ResetTimer() { panic("not yet implemented") } +func (b *B) Run(name string, f func(b *B)) bool { panic("not yet implemented") } +func (b *B) RunParallel(body func(*PB)) { panic("not yet implemented") } +func (b *B) SetBytes(n int64) { panic("not yet implemented") } +func (b *B) SetParallelism(p int) { panic("not yet implemented") } +func (b *B) Setenv(key, value string) { panic("not yet implemented") } +func (b *B) Skip(args ...any) { panic("not yet implemented") } +func (b *B) SkipNow() { panic("not yet implemented") } +func (b *B) Skipf(format string, args ...any) { panic("not yet implemented") } +func (b *B) Skipped() bool { panic("not yet implemented") } +func (b *B) StartTimer() { panic("not yet implemented") } +func (b *B) StopTimer() { panic("not yet implemented") } +func (b *B) TempDir() string { panic("not yet implemented") } + +// ---------------------------------------- +// PB +// TODO: actually implement + +type PB struct{} + +func (pb *PB) Next() bool { panic("not yet implemented") } + +type InternalTest struct { + Name string + F testingFunc +} + +func (t *T) shouldRun(name string) bool { + if t.runFilter == nil { + return true + } + + elem := strings.Split(name, "/") + ok, partial := t.runFilter.matches(elem) + _ = partial // we don't care right now + return ok +} + +func RunTest(runFlag string, verbose bool, failfast bool, test InternalTest) (ret string) { + t := &T{ + name: test.Name, + verbose: verbose, + failfast: failfast, + } + + if runFlag != "" { + t.runFilter = splitRegexp(runFlag) + } + + tRunner(t, test.F, verbose) + if !t.verbose && t.Failed() { + // use printFailure to print output log of this + // and/or any subtests that may have failed. + t.printFailure() + } + + report := t.report() + return report.marshal() +} + +func formatDur(dur int64) string { + // XXX switch to FormatFloat after it's been added + // 1 sec = 1e9 nsec + // this gets us the "centiseconds" which is what we show in tests. + dstr := strconv.Itoa(int(dur / 1e7)) + if len(dstr) < 3 { + const pad = "000" + dstr = pad[:3-len(dstr)] + dstr + } + return dstr[:len(dstr)-2] + "." + dstr[len(dstr)-2:] + "s" +} + +// used to calculate execution times; only present in testing stdlibs +func unixNano() int64 + +// recovers panics and returns their related stacktraces, as well +func recoverWithStacktrace() (interface{}, string) + +// used to filter tests, we can't directly use regexp here due to a cyclic import; only present in testing stdlibs +func matchString(pat, str string) (bool, string) + +func tRunner(t *T, fn testingFunc, verbose bool) { + if !t.shouldRun(t.name) { + return + } + + start := unixNano() + + defer func() { + err, st := recoverWithStacktrace() + switch err.(type) { + case nil: + case SkipErr: + default: + t.Fail() + fmt.Fprintf(os.Stderr, "panic: %v\nStacktrace:\n%s\n", err, st) + } + + dur := unixNano() - start + t.dur = formatDur(dur) + + if t.verbose { + switch { + case t.Failed(): + fmt.Fprintf(os.Stderr, "--- FAIL: %s (%s)\n", t.name, t.dur) + case t.skipped: + fmt.Fprintf(os.Stderr, "--- SKIP: %s (%s)\n", t.name, t.dur) + case t.verbose: + fmt.Fprintf(os.Stderr, "--- PASS: %s (%s)\n", t.name, t.dur) + } + } + }() + + if verbose { + fmt.Fprintf(os.Stderr, "=== RUN %s\n", t.name) + } + + fn(t) +} diff --git a/gnovm/stdlibs/testing/base/testing.go b/gnovm/stdlibs/testing/base/testing.go new file mode 100644 index 00000000000..520f333b563 --- /dev/null +++ b/gnovm/stdlibs/testing/base/testing.go @@ -0,0 +1,18 @@ +package base + +import ( + "github.com/gnolang/gno/gnovm/pkg/gnolang" +) + +func X_unixNano() int64 { + // only implemented in testing stdlibs + return 0 +} + +func X_matchString(pat, str string) (bool, string) { + panic("only implemented in testing stdlibs") +} + +func X_recoverWithStacktrace() (gnolang.TypedValue, string) { + panic("only available in testing stdlibs") +} diff --git a/gnovm/stdlibs/testing/testing.gno b/gnovm/stdlibs/testing/testing.gno index 9b9859642c3..bbd88936894 100644 --- a/gnovm/stdlibs/testing/testing.gno +++ b/gnovm/stdlibs/testing/testing.gno @@ -2,24 +2,14 @@ package testing import ( - "fmt" - "os" - "strconv" - "strings" + "testing/base" ) +// XXX everything actually declared in testing/base + // ---------------------------------------- // Top level functions -// skipErr is the type of the panic created by SkipNow -// and FailNow. Having it as a simple string means that it can be fmt.Printf'd -// easily (and doesn't get "corrupted" through gno2go). -type skipErr string - -func (s skipErr) Error() string { - return string(s) -} - // Recover functions like recover(), but it ensures that the recovered error is // not an internal error of the testing package. // @@ -28,357 +18,39 @@ func (s skipErr) Error() string { // (and Skip* functions). // // NOTE: Recover() is likely to be removed. -func Recover(result Setter) { - r := recover() - if _, ok := r.(skipErr); !ok { - result.Set(r) - return - } - - panic(r) -} +var Recover = base.Recover -type Setter interface { - Set(v any) -} +type Setter = base.Setter -func Short() bool { - return true // TODO configure somehow. -} +var Short = base.Short -func Verbose() bool { - return true // TODO configure somehow. -} +var Verbose = base.Verbose // Like AllocsPerRun() but returns an integer. // TODO: actually compute allocations; for now return 0. -func AllocsPerRun2(runs int, f func()) (total int) { - for i := 0; i < runs; i++ { - f() - } - return 0 -} +var AllocsPerRun2 = base.AllocsPerRun2 // ---------------------------------------- // T -type T struct { - name string - failed bool - skipped bool - subs []*T - parent *T - output []byte // Output generated by test - verbose bool - failfast bool - runFilter filterMatch - dur string -} - -func NewT(name string) *T { - return &T{name: name} -} - -type testingFunc func(*T) - -// Not yet implemented: -// func (t *T) Cleanup(f func()) { -// func (t *T) Deadline() (deadline time.Time, ok bool) -func (t *T) Error(args ...any) { - t.Log(args...) - t.Fail() -} - -func (t *T) Errorf(format string, args ...any) { - t.Logf(format, args...) - t.Fail() -} - -func (t *T) Fail() { - t.failed = true -} - -func (t *T) FailNow() { - t.Fail() - panic(skipErr("testing: you have recovered a panic attempting to interrupt a test, as a consequence of FailNow. " + - "Use testing.Recover to recover panics within tests")) -} - -func (t *T) Failed() bool { - if t.failed { - return true - } - for _, sub := range t.subs { - if sub.Failed() { - return true - } - } - return false -} - -// only called when verbose == false -func (t *T) printFailure() { - fmt.Fprintf(os.Stderr, "--- FAIL: %s (%s)\n", t.name, t.dur) - if t.failed { - fmt.Fprint(os.Stderr, string(t.output)) - } - for _, sub := range t.subs { - if sub.Failed() { - sub.printFailure() - } - } -} - -func (t *T) Fatal(args ...any) { - t.Log(args...) - t.FailNow() -} - -func (t *T) Fatalf(format string, args ...any) { - t.Logf(format, args...) - t.FailNow() -} - -func (t *T) Log(args ...any) { - t.log(fmt.Sprintln(args...)) -} - -func (t *T) Logf(format string, args ...any) { - t.log(fmt.Sprintf(format, args...)) - t.log(fmt.Sprintln()) -} - -func (t *T) Name() string { - return t.name -} - -func (t *T) Parallel() { - // does nothing. -} - -func (t *T) Run(name string, f testingFunc) bool { - fullName := t.name + "/" + rewrite(name) - - subT := &T{ - parent: t, - name: fullName, - verbose: t.verbose, - runFilter: t.runFilter, - } - - if t.failfast && t.Failed() { - return false - } - - t.subs = append(t.subs, subT) - - tRunner(subT, f, t.verbose) - return true -} - -func (t *T) Setenv(key, value string) { - panic("not yet implemented") -} - -func (t *T) Skip(args ...any) { - t.Log(args...) - t.SkipNow() -} +type T = base.T -func (t *T) SkipNow() { - t.skipped = true - panic(skipErr("testing: you have recovered a panic attempting to interrupt a test, as a consequence of SkipNow. " + - "Use testing.Recover to recover panics within tests")) -} +var NewT = base.NewT -func (t *T) Skipped() bool { - return t.skipped -} - -func (t *T) Skipf(format string, args ...any) { - t.Logf(format, args...) - t.SkipNow() -} - -func (t *T) TempDir() string { - panic("not yet implemented") -} - -func (t *T) Helper() { -} - -func (t *T) log(s string) { - if t.verbose { - // verbose, print immediately - fmt.Fprint(os.Stderr, s) - } else { - // defer printing only if test is failed - t.output = append(t.output, s...) - } -} - -type Report struct { - Failed bool - Skipped bool -} - -func (r *Report) marshal() string { - failed := "false" - skipped := "false" - if r.Failed { - failed = "true" - } - if r.Skipped { - skipped = "true" - } - return `{"Failed":` + failed + `,"Skipped":` + skipped + `}` -} - -func (t *T) report() Report { - return Report{ - Failed: t.Failed(), - Skipped: t.skipped, - } -} +type Report = base.Report // ---------------------------------------- // B // TODO: actually implement -type B struct { - N int -} - -func (b *B) Cleanup(f func()) { panic("not yet implemented") } -func (b *B) Error(args ...any) { panic("not yet implemented") } -func (b *B) Errorf(format string, args ...any) { panic("not yet implemented") } -func (b *B) Fail() { panic("not yet implemented") } -func (b *B) FailNow() { panic("not yet implemented") } -func (b *B) Failed() bool { panic("not yet implemented") } -func (b *B) Fatal(args ...any) { panic("not yet implemented") } -func (b *B) Fatalf(format string, args ...any) { panic("not yet implemented") } -func (b *B) Helper() { panic("not yet implemented") } -func (b *B) Log(args ...any) { panic("not yet implemented") } -func (b *B) Logf(format string, args ...any) { panic("not yet implemented") } -func (b *B) Name() string { panic("not yet implemented") } -func (b *B) ReportAllocs() { panic("not yet implemented") } -func (b *B) ReportMetric(n float64, unit string) { panic("not yet implemented") } -func (b *B) ResetTimer() { panic("not yet implemented") } -func (b *B) Run(name string, f func(b *B)) bool { panic("not yet implemented") } -func (b *B) RunParallel(body func(*PB)) { panic("not yet implemented") } -func (b *B) SetBytes(n int64) { panic("not yet implemented") } -func (b *B) SetParallelism(p int) { panic("not yet implemented") } -func (b *B) Setenv(key, value string) { panic("not yet implemented") } -func (b *B) Skip(args ...any) { panic("not yet implemented") } -func (b *B) SkipNow() { panic("not yet implemented") } -func (b *B) Skipf(format string, args ...any) { panic("not yet implemented") } -func (b *B) Skipped() bool { panic("not yet implemented") } -func (b *B) StartTimer() { panic("not yet implemented") } -func (b *B) StopTimer() { panic("not yet implemented") } -func (b *B) TempDir() string { panic("not yet implemented") } +type B = base.B // ---------------------------------------- // PB // TODO: actually implement -type PB struct{} - -func (pb *PB) Next() bool { panic("not yet implemented") } - -type InternalTest struct { - Name string - F testingFunc -} - -func (t *T) shouldRun(name string) bool { - if t.runFilter == nil { - return true - } - - elem := strings.Split(name, "/") - ok, partial := t.runFilter.matches(elem) - _ = partial // we don't care right now - return ok -} - -func RunTest(runFlag string, verbose bool, failfast bool, test InternalTest) (ret string) { - t := &T{ - name: test.Name, - verbose: verbose, - failfast: failfast, - } - - if runFlag != "" { - t.runFilter = splitRegexp(runFlag) - } - - tRunner(t, test.F, verbose) - if !t.verbose && t.Failed() { - // use printFailure to print output log of this - // and/or any subtests that may have failed. - t.printFailure() - } - - report := t.report() - return report.marshal() -} - -func formatDur(dur int64) string { - // XXX switch to FormatFloat after it's been added - // 1 sec = 1e9 nsec - // this gets us the "centiseconds" which is what we show in tests. - dstr := strconv.Itoa(int(dur / 1e7)) - if len(dstr) < 3 { - const pad = "000" - dstr = pad[:3-len(dstr)] + dstr - } - return dstr[:len(dstr)-2] + "." + dstr[len(dstr)-2:] + "s" -} - -// used to calculate execution times; only present in testing stdlibs -func unixNano() int64 - -// recovers panics and returns their related stacktraces, as well -func recoverWithStacktrace() (interface{}, string) - -// used to filter tests, we can't directly use regexp here due to a cyclic import; only present in testing stdlibs -func matchString(pat, str string) (bool, string) - -func tRunner(t *T, fn testingFunc, verbose bool) { - if !t.shouldRun(t.name) { - return - } - - start := unixNano() - - defer func() { - err, st := recoverWithStacktrace() - switch err.(type) { - case nil: - case skipErr: - default: - t.Fail() - fmt.Fprintf(os.Stderr, "panic: %v\nStacktrace:\n%s\n", err, st) - } - - dur := unixNano() - start - t.dur = formatDur(dur) - - if t.verbose { - switch { - case t.Failed(): - fmt.Fprintf(os.Stderr, "--- FAIL: %s (%s)\n", t.name, t.dur) - case t.skipped: - fmt.Fprintf(os.Stderr, "--- SKIP: %s (%s)\n", t.name, t.dur) - case t.verbose: - fmt.Fprintf(os.Stderr, "--- PASS: %s (%s)\n", t.name, t.dur) - } - } - }() +type PB = base.PB - if verbose { - fmt.Fprintf(os.Stderr, "=== RUN %s\n", t.name) - } +type InternalTest = base.InternalTest - fn(t) -} +var RunTest = base.RunTest diff --git a/gnovm/tests/files/alloc_5.gno b/gnovm/tests/files/alloc_5.gno index f7ad6b147c1..d2f2045241a 100644 --- a/gnovm/tests/files/alloc_5.gno +++ b/gnovm/tests/files/alloc_5.gno @@ -5,6 +5,9 @@ import "runtime" func gen() { data := make([]byte, 50*1024*1024) + if false { + println(data) + } } // this is mainly for gas usage check diff --git a/gnovm/tests/files/alloc_6.gno b/gnovm/tests/files/alloc_6.gno index a23f86cce96..39f5cc7d962 100644 --- a/gnovm/tests/files/alloc_6.gno +++ b/gnovm/tests/files/alloc_6.gno @@ -7,6 +7,9 @@ func main() { var a = func() int { return 1 } + if false { + a() + } runtime.GC() println("memstats in main after GC: ", runtime.MemStats()) diff --git a/gnovm/tests/files/alloc_6a.gno b/gnovm/tests/files/alloc_6a.gno index d2e76b6bd56..143537ee7bb 100644 --- a/gnovm/tests/files/alloc_6a.gno +++ b/gnovm/tests/files/alloc_6a.gno @@ -8,6 +8,9 @@ func main() { var a = func() int { return 1 } + if false { + a() + } runtime.GC() } diff --git a/misc/genstd/package_sort.go b/misc/genstd/package_sort.go index 575f56d9506..daf3bd366b4 100644 --- a/misc/genstd/package_sort.go +++ b/misc/genstd/package_sort.go @@ -37,7 +37,8 @@ func sortPackages(pkgs []*pkgData) []string { if slices.Contains(res, imp) { continue } - if pkg.importPath == "testing" && + if (pkg.importPath == "testing" || + pkg.importPath == "testing/base") && slices.Contains(nativeInjections, imp) { continue } From 6c37d6705347699a948db0e14f67091aaa985ae9 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 15 May 2025 11:10:17 -0700 Subject: [PATCH 22/83] intermediate... --- gnovm/pkg/gnolang/machine.go | 10 ++++-- gnovm/pkg/gnolang/nodes.go | 11 ++++++ gnovm/pkg/gnolang/nodes_span.go | 4 +++ gnovm/pkg/gnolang/preprocess.go | 63 ++++++++++++++++++++++++++------- gnovm/tests/files/alloc_5.gno | 3 -- gnovm/tests/files/alloc_6.gno | 3 -- gnovm/tests/files/alloc_6a.gno | 3 -- gnovm/tests/files/closure.gno | 2 +- 8 files changed, 74 insertions(+), 25 deletions(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index a7d35a43274..91a56389ef6 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -432,6 +432,7 @@ func (m *Machine) Stacktrace() (stacktrace Stacktrace) { // Production must not use this, because realm package init // must happen after persistence and realm finalization, // then changes from init persisted again. +// m.Package must match fns's package path. func (m *Machine) RunFiles(fns ...*FileNode) { pv := m.Package if pv == nil { @@ -508,6 +509,7 @@ func (m *Machine) PreprocessFiles(pkgName, pkgPath string, fset *FileSet, save, // Add files to the package's *FileSet and run decls in them. // This will also run each init function encountered. // Returns the updated typed values of package. +// m.Package must match fns's package path. func (m *Machine) runFileDecls(withOverrides bool, fns ...*FileNode) []TypedValue { // Files' package names must match the machine's active one. // if there is one. @@ -559,6 +561,7 @@ func (m *Machine) runFileDecls(withOverrides bool, fns ...*FileNode) []TypedValu if debug { debug.Printf("PREPROCESSED FILE: %v\n", fn) } + // fmt.Println("PREPROCESSED", fn) // After preprocessing, save blocknodes to store. SaveBlockNodes(m.Store, fn) // Make block for fn. @@ -600,8 +603,8 @@ func (m *Machine) runFileDecls(withOverrides bool, fns ...*FileNode) []TypedValu continue } else { // is an undefined dependency. panic(fmt.Sprintf( - "dependency %s not defined in fileset with files %v", - dep, fs.FileNames())) + "%s/%s:%s: dependency %s not defined in fileset with files %v", + pv.PkgPath, fn.Name, decl.GetPos().String(), dep, fs.FileNames())) } } // if dep already in loopfindr, abort. @@ -612,7 +615,8 @@ func (m *Machine) runFileDecls(withOverrides bool, fns ...*FileNode) []TypedValu continue } else { panic(fmt.Sprintf( - "loop in variable initialization: dependency trail %v circularly depends on %s", loopfindr, dep)) + "%s/%s:%s: loop in variable initialization: dependency trail %v circularly depends on %s", + pv.PkgPath, fn.Name, decl.GetPos().String(), loopfindr, dep)) } } // run dependency declaration diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 7d3a16fc63f..da892791a21 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -113,6 +113,16 @@ const ( type Name string +type Names []Name + +func (ns Names) Join(j string) string { + ss := make([]string, 0, len(ns)) + for _, n := range ns { + ss = append(ss, string(n)) + } + return strings.Join(ss, j) +} + // ---------------------------------------- // Attributes // All nodes have attributes for general analysis purposes. @@ -202,6 +212,7 @@ type Node interface { assertNode() String() string Copy() Node + GetPos() Pos GetLine() int GetColumn() int GetSpan() Span diff --git a/gnovm/pkg/gnolang/nodes_span.go b/gnovm/pkg/gnolang/nodes_span.go index ca6508b7ef4..3222f499c8f 100644 --- a/gnovm/pkg/gnolang/nodes_span.go +++ b/gnovm/pkg/gnolang/nodes_span.go @@ -41,6 +41,10 @@ type Pos struct { Column int } +func (p Pos) GetPos() Pos { + return p +} + func (p Pos) GetLine() int { return p.Line } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c5f598e17bc..2a0e327b116 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -453,6 +453,7 @@ var preprocessing atomic.Int32 // - Assigns BlockValuePath to NameExprs. // - TODO document what it does. func Preprocess(store Store, ctx BlockNode, n Node) Node { + var clearSkip = false // First init static blocks of blocknodes. // This may have already happened. // Keep this function idemponent. @@ -463,12 +464,31 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if stage != TRANS_ENTER { return n, TRANS_CONTINUE } + if _, ok := n.(*FuncLitExpr); ok { + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + clearSkip = true // clear what preprocess1 will do. + return n, TRANS_SKIP + } + } if bn, ok := n.(BlockNode); ok { initStaticBlocks(store, ctx, bn) return n, TRANS_SKIP } return n, TRANS_CONTINUE }) + if clearSkip { + defer func() { + Transcribe(n, + func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + if stage != TRANS_ENTER { + return n, TRANS_CONTINUE + } + n.DelAttribute(ATTR_PREPROCESS_SKIPPED) + n.DelAttribute(ATTR_PREPROCESS_INCOMPLETE) + return n, TRANS_CONTINUE + }) + }() + } // Bulk of the preprocessor function n = preprocess1(store, ctx, n) @@ -486,6 +506,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if stage != TRANS_ENTER { return n, TRANS_CONTINUE } + if _, ok := n.(*FuncLitExpr); ok { + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + return n, TRANS_SKIP + } + } if bn, ok := n.(BlockNode); ok { // findGotoLoopDefines(ctx, bn) findHeapDefinesByUse(ctx, bn) @@ -702,6 +727,8 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // retrieve cached function type. ft := evalStaticType(store, last, &n.Type).(*FuncType) if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + // Machine still needs it. Clear it @ initStaticBlocks. + // n.DelAttribute(ATTR_PREPROCESS_SKIPPED) for _, p := range ns { p.SetAttribute(ATTR_PREPROCESS_INCOMPLETE, true) } @@ -2841,6 +2868,7 @@ func findHeapDefinesByUse(ctx BlockNode, bn BlockNode) { }) } +// TODO consider adding to Names type. func addName(names []Name, name Name) []Name { if !slices.Contains(names, name) { names = append(names, name) @@ -3829,12 +3857,19 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin if direct { if astype { if _, ok := defining[cx.Name]; ok { - panic("RECURSIVE" + string(cx.Name)) // XXX + panic(fmt.Sprintf("invalid recursive type: %s -> %s", + Names(stack).Join(" -> "), cx.Name)) } if tv := last.GetValueRef(store, cx.Name, true); tv != nil { return } } else { + /* + if _, ok := defining[cx.Name]; !ok { + fmt.Println("AAAA") + return cx.Name + } + */ if tv := last.GetValueRef(store, cx.Name, true); tv == nil { return cx.Name panic("RECURSIVE") @@ -3844,9 +3879,9 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin return } } else { - } - if tv := last.GetValueRef(store, cx.Name, true); tv != nil { - return + if tv := last.GetValueRef(store, cx.Name, true); tv != nil { + return + } } return cx.Name case *BasicLitExpr: @@ -3885,7 +3920,7 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin return } } - case *StarExpr: + case *StarExpr: // POINTER & DEREF // NOTE: *StarExpr can either mean dereference, or a pointer type. // It's not only confusing for new developers, it causes complexity // in type checking. A *StarExpr is indirect as a type. @@ -4113,14 +4148,15 @@ func predefineRecursively(store Store, last BlockNode, d Decl) bool { defer doRecover([]BlockNode{last}, d) stack := []Name{} defining := make(map[Name]struct{}) - return predefineRecursively2(store, last, d, stack, defining) + direct := true + return predefineRecursively2(store, last, d, stack, defining, direct) } // `stack` and `defining` are used for cycle detection. They hold the same data. // NOTE: `stack` never truncates; a slice is used instead of a map to show a // helpful message when a circular declaration is found. `defining` is also used as // a map to ensure best time performance of circular definition detection. -func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}) bool { +func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}, direct bool) bool { pkg := packageOf(last) // NOTE: predefine fileset breaks up circular definitions like @@ -4145,8 +4181,11 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de }() // recursively predefine any dependencies. + var un Name // unnamed name + // var direct = true // invalid cycle detection for { - un := tryPredefine(store, pkg, last, d, stack, defining) + //un, direct = tryPredefine(store, pkg, last, d, stack, defining) + un = tryPredefine(store, pkg, last, d, stack, defining, direct) if un != "" { // check circularity. if _, exists := defining[un]; exists { @@ -4160,7 +4199,7 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de panic("all types from files in file-set should have already been predefined") } // predefine dependency recursively. - predefineRecursively2(store, file, *unDecl, stack, defining) + predefineRecursively2(store, file, *unDecl, stack, defining, direct) } else { break // predefine successfully performed. } @@ -4193,7 +4232,7 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de // If all dependencies are met, constructs and empty definition value (for a // *TypeDecl is a TypeValue) and sets it on last. As an exception, *FuncDecls // will preprocess receiver/argument/result types recursively. -func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}) (un Name) { +func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}, direct bool) (un Name) { if d.GetAttribute(ATTR_PREDEFINED) == true { panic(fmt.Sprintf("decl node already predefined! %v", d)) } @@ -4274,7 +4313,7 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ // `var a, b, c = 1, a, b` was already split up before reaching // here, whereas they are illegal inside a function. for _, vx := range d.Values { - un = findUndefinedV(store, last, vx, stack, defining, true, nil) + un = findUndefinedV(store, last, vx, stack, defining, direct, nil) if un != "" { return } @@ -4380,7 +4419,7 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ d.Path = last.GetPathForName(store, d.Name) } // END *TypeDecl // after predefinitions, return any undefined dependencies. - un = findUndefinedT(store, last, d.Type, stack, defining, true) + un = findUndefinedT(store, last, d.Type, stack, defining, direct) if un != "" { return } diff --git a/gnovm/tests/files/alloc_5.gno b/gnovm/tests/files/alloc_5.gno index d2f2045241a..7bc5838353b 100644 --- a/gnovm/tests/files/alloc_5.gno +++ b/gnovm/tests/files/alloc_5.gno @@ -23,6 +23,3 @@ func main() { // Output: // memstats in main after GC: Allocator{maxBytes:100000000, bytes:6036} - -// TypeCheckError: -// main/alloc_5.gno:7:2: declared and not used: data diff --git a/gnovm/tests/files/alloc_6.gno b/gnovm/tests/files/alloc_6.gno index 39f5cc7d962..70e0264f83e 100644 --- a/gnovm/tests/files/alloc_6.gno +++ b/gnovm/tests/files/alloc_6.gno @@ -17,6 +17,3 @@ func main() { // Output: // memstats in main after GC: Allocator{maxBytes:100000000, bytes:6036} - -// TypeCheckError: -// main/alloc_6.gno:7:6: declared and not used: a diff --git a/gnovm/tests/files/alloc_6a.gno b/gnovm/tests/files/alloc_6a.gno index 143537ee7bb..4f400a43dd9 100644 --- a/gnovm/tests/files/alloc_6a.gno +++ b/gnovm/tests/files/alloc_6a.gno @@ -19,6 +19,3 @@ func main() { // Output: // memstats in main after GC: Allocator{maxBytes:100000000, bytes:6542} - -// TypeCheckError: -// main/alloc_6a.gno:8:7: declared and not used: a diff --git a/gnovm/tests/files/closure.gno b/gnovm/tests/files/closure.gno index 2085bc78ac6..3804ef8dc7d 100644 --- a/gnovm/tests/files/closure.gno +++ b/gnovm/tests/files/closure.gno @@ -13,7 +13,7 @@ var b = func() { } // Error: -// main/closure.gno:7:5: constant definition loop with a +// main/closure.gno:7:5: loop in variable initialization: dependency trail [b a] circularly depends on b // TypeCheckError: // main/closure.gno:7:5: initialization cycle for a; main/closure.gno:7:5: a refers to b; main/closure.gno:11:5: b refers to a From 3bc9349cfc3c53dc8ebb2d912a568592a2bb13d1 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 15 May 2025 23:43:30 -0700 Subject: [PATCH 23/83] fix more tests --- gnovm/pkg/gnolang/preprocess.go | 214 ++++++++++++++---------- gnovm/pkg/gnolang/types.go | 1 + gnovm/tests/files/circular_constant.gno | 2 +- gnovm/tests/files/const34.gno | 2 +- gnovm/tests/files/const9.gno | 2 +- 5 files changed, 129 insertions(+), 92 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 2a0e327b116..19f24faa197 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -15,6 +15,7 @@ import ( const ( blankIdentifier = "_" + debugFind = false //true // toggle when debugging. ) // Predefine (initStaticBlocks) and partially evaluates all names @@ -3828,32 +3829,53 @@ func convertConst(store Store, last BlockNode, n Node, cx *ConstExpr, t Type) { // // Args: // - direct: If true x must not be a *NameExpr in stack/defining (illegal direct recursion). -// - t: for composite type eliding -func findUndefinedV(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool, t Type) (un Name) { - return findUndefinedAny(store, last, x, stack, defining, direct, false, t) +// - elide: For composite type eliding. +// +// Returns: +// - un: undefined dependency's name if any +// - directR: if un != "", `direct` passed to final name expr. +// NOTE: 'direct' is passed through, or becomes overridden with false and +// passed to higher/later calls in the stack, and the `direct` argument +// seen at the top of the stack is returned all the way back. +func findUndefinedV(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool, elide Type) (un Name, directR bool) { + return findUndefinedAny(store, last, x, stack, defining, false, direct, false, elide) } -func findUndefinedT(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool) (un Name) { - return findUndefinedAny(store, last, x, stack, defining, direct, true, nil) +func findUndefinedT(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, isalias bool, direct bool) (un Name, directR bool) { + return findUndefinedAny(store, last, x, stack, defining, isalias, direct, true, nil) } -func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, direct bool, astype bool, t Type) (un Name) { +func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, defining map[Name]struct{}, isalias bool, direct bool, astype bool, elide Type) (un Name, directR bool) { + if debugFind { + fmt.Printf("findUndefinedAny(%v, %v, %v, isalias=%v, direct=%v, astype=%v, elide=%v\n", x, stack, defining, isalias, direct, astype, elide) + } if x == nil { return } switch cx := x.(type) { case *NameExpr: if _, ok := UverseNode().GetLocalIndex(cx.Name); ok { - // XXX NOTE even if the name is shadowed by a file - // level declaration, it is fine to return here as it - // will be predefined later and fail then. return } /* if _, ok := defining[cx.Name]; !ok { return cx.Name } + + else if idx, ok := UverseNode().GetLocalIndex(tx.Name); ok { + // uverse name + path := NewValuePathUverse(idx, tx.Name) + tv := Uverse().GetValueAt(nil, path) + t = tv.GetType() + } else { + // yet undefined + un = tx.Name + directR = direct // returns along callstack. + untype = true + return + } */ + // XXX simplify if direct { if astype { if _, ok := defining[cx.Name]; ok { @@ -3864,58 +3886,49 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin return } } else { - /* - if _, ok := defining[cx.Name]; !ok { - fmt.Println("AAAA") - return cx.Name - } - */ - if tv := last.GetValueRef(store, cx.Name, true); tv == nil { - return cx.Name - panic("RECURSIVE") - fmt.Println("NAME", cx, "DEFINED (OK)") + if tv := last.GetValueRef(store, cx.Name, true); tv != nil { return } - return + return cx.Name, direct } } else { if tv := last.GetValueRef(store, cx.Name, true); tv != nil { return } } - return cx.Name + return cx.Name, direct case *BasicLitExpr: return case *BinaryExpr: - un = findUndefinedV(store, last, cx.Left, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Left, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedV(store, last, cx.Right, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Right, stack, defining, direct, nil) if un != "" { return } case *SelectorExpr: return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *SliceExpr: - un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } if cx.Low != nil { - un = findUndefinedV(store, last, cx.Low, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Low, stack, defining, direct, nil) if un != "" { return } } if cx.High != nil { - un = findUndefinedV(store, last, cx.High, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.High, stack, defining, direct, nil) if un != "" { return } } if cx.Max != nil { - un = findUndefinedV(store, last, cx.Max, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Max, stack, defining, direct, nil) if un != "" { return } @@ -3923,32 +3936,32 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin case *StarExpr: // POINTER & DEREF // NOTE: *StarExpr can either mean dereference, or a pointer type. // It's not only confusing for new developers, it causes complexity - // in type checking. A *StarExpr is indirect as a type. + // in type checking. A *StarExpr is indirect as a type unless alias. if astype { - return findUndefinedT(store, last, cx.X, stack, defining, false) + return findUndefinedT(store, last, cx.X, stack, defining, isalias, isalias) } else { return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) } case *RefExpr: return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *TypeAssertExpr: - un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } - return findUndefinedT(store, last, cx.Type, stack, defining, direct) + return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) case *UnaryExpr: return findUndefinedV(store, last, cx.X, stack, defining, direct, nil) case *CompositeLitExpr: var ct Type if cx.Type == nil { - if t == nil { + if elide == nil { panic("cannot elide unknown composite type") } - ct = t - cx.Type = constType(cx, t) + ct = elide + cx.Type = constType(cx, elide) } else { - un = findUndefinedT(store, last, cx.Type, stack, defining, direct) + un, directR = findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) if un != "" { return } @@ -3965,18 +3978,18 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin switch ct.Kind() { case ArrayKind, SliceKind, MapKind: for _, kvx := range cx.Elts { - un = findUndefinedV(store, last, kvx.Key, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, kvx.Key, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedV(store, last, kvx.Value, stack, defining, direct, ct.Elem()) + un, directR = findUndefinedV(store, last, kvx.Value, stack, defining, direct, ct.Elem()) if un != "" { return } } case StructKind: for _, kvx := range cx.Elts { - un = findUndefinedV(store, last, kvx.Value, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, kvx.Value, stack, defining, direct, nil) if un != "" { return } @@ -3987,86 +4000,88 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin ct.String())) } case *FuncLitExpr: - /* XXX delete - // TODO recursive preprocessing here is hacky, find a better - // way. This cannot be done asynchronously, cuz undefined - // names ought to be returned immediately to let the caller - // predefine it. - cx.Type = Preprocess(store, last, cx.Type).(Expr) // recursive - ct = evalStaticType(store, last, cx.Type) - */ - un = findUndefinedT(store, last, &cx.Type, stack, defining, direct) + // XXX why would astype && be necessary? + un, directR = findUndefinedT(store, last, &cx.Type, stack, defining, isalias, astype && isalias) if un != "" { return } cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") case *FieldTypeExpr: // FIELD - return findUndefinedT(store, last, cx.Type, stack, defining, direct) + return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) case *ArrayTypeExpr: if cx.Len != nil { - un = findUndefinedV(store, last, cx.Len, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Len, stack, defining, direct, nil) if un != "" { return } } - return findUndefinedT(store, last, cx.Elt, stack, defining, direct) + return findUndefinedT(store, last, cx.Elt, stack, defining, isalias, direct) case *SliceTypeExpr: - return findUndefinedT(store, last, cx.Elt, stack, defining, false) + return findUndefinedT(store, last, cx.Elt, stack, defining, isalias, astype && isalias) case *InterfaceTypeExpr: for i := range cx.Methods { - un = findUndefinedT(store, last, &cx.Methods[i], stack, defining, false) + method := &cx.Methods[i] + direct2 := false + if _, ok := method.Type.(*NameExpr); ok { + direct2 = true + } + un, directR = findUndefinedT(store, last, &cx.Methods[i], stack, defining, isalias, direct2) if un != "" { return } } case *ChanTypeExpr: - return findUndefinedT(store, last, cx.Value, stack, defining, false) + return findUndefinedT(store, last, cx.Value, stack, defining, isalias, astype && isalias) case *FuncTypeExpr: for i := range cx.Params { - un = findUndefinedT(store, last, &cx.Params[i], stack, defining, false) + un, directR = findUndefinedT(store, last, &cx.Params[i], stack, defining, isalias, astype && isalias) if un != "" { return } } for i := range cx.Results { - un = findUndefinedT(store, last, &cx.Results[i], stack, defining, false) + un, directR = findUndefinedT(store, last, &cx.Results[i], stack, defining, isalias, astype && isalias) if un != "" { return } } - case *MapTypeExpr: - un = findUndefinedT(store, last, cx.Key, stack, defining, false) + case *MapTypeExpr: // MAP + un, directR = findUndefinedT(store, last, cx.Key, stack, defining, isalias, astype && isalias) if un != "" { return } - un = findUndefinedT(store, last, cx.Value, stack, defining, false) + // e.g.; + // type Int = map[Int]IntIllegal; + // type Int = struct{Int}; + // type Int = *Int; + un, directR = findUndefinedT(store, last, cx.Value, stack, defining, isalias, isalias) if un != "" { return } case *StructTypeExpr: // STRUCT for i := range cx.Fields { - un = findUndefinedT(store, last, &cx.Fields[i], stack, defining, direct) + un, directR = findUndefinedT(store, last, &cx.Fields[i], stack, defining, isalias, direct) if un != "" { return } } case *CallExpr: - un = findUndefinedV(store, last, cx.Func, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Func, stack, defining, direct, nil) if un != "" { return } for i := range cx.Args { - un = findUndefinedV(store, last, cx.Args[i], stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Args[i], stack, defining, direct, nil) if un != "" { return } } case *IndexExpr: - un = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.X, stack, defining, direct, nil) if un != "" { return } - un = findUndefinedV(store, last, cx.Index, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, cx.Index, stack, defining, direct, nil) if un != "" { return } @@ -4181,16 +4196,26 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de }() // recursively predefine any dependencies. - var un Name // unnamed name + var un Name // undefined name + var untype bool + var directR bool // var direct = true // invalid cycle detection for { - //un, direct = tryPredefine(store, pkg, last, d, stack, defining) - un = tryPredefine(store, pkg, last, d, stack, defining, direct) + un, untype, directR = tryPredefine(store, pkg, last, d, stack, defining, direct) + if debugFind { + fmt.Printf("tryPredefine(%v, %v, defining=%v, direct=%v)-->un=%v,untype=%v,direct2=%v\n", d, stack, defining, direct, un, untype, directR) + } if un != "" { - // check circularity. + // `un` is undefined, so define recursively. + // first, check circularity. if _, exists := defining[un]; exists { - // XXX use stack to show the cycle. - panic(fmt.Sprintf("constant definition loop with %s", un)) + if untype { + panic(fmt.Sprintf("invalid recursive type: %s -> %s", + Names(stack).Join(" -> "), un)) + } else { + panic(fmt.Sprintf("invalid recursive value: %s -> %s", + Names(stack).Join(" -> "), un)) + } } // look up dependency declaration from fileset. file, unDecl := pkg.FileSet.GetDeclFor(un) @@ -4199,7 +4224,8 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de panic("all types from files in file-set should have already been predefined") } // predefine dependency recursively. - predefineRecursively2(store, file, *unDecl, stack, defining, direct) + // `directR` is passed on. + predefineRecursively2(store, file, *unDecl, stack, defining, directR) } else { break // predefine successfully performed. } @@ -4232,7 +4258,7 @@ func predefineRecursively2(store Store, last BlockNode, d Decl, stack []Name, de // If all dependencies are met, constructs and empty definition value (for a // *TypeDecl is a TypeValue) and sets it on last. As an exception, *FuncDecls // will preprocess receiver/argument/result types recursively. -func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}, direct bool) (un Name) { +func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack []Name, defining map[Name]struct{}, direct bool) (un Name, untype bool, directR bool) { if d.GetAttribute(ATTR_PREDEFINED) == true { panic(fmt.Sprintf("decl node already predefined! %v", d)) } @@ -4304,17 +4330,19 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ if isBlankIdentifier(d.Type) { panic("cannot use _ as value or type") } - - un = findUndefinedT(store, last, d.Type, stack, defining, false) // XXX + isalias := false // a value decl can't be. + un, directR = findUndefinedT(store, last, d.Type, stack, defining, isalias, false) // XXX if un != "" { + untype = true return } // NOTE: cyclic *ValueDecl at the package/file level such as // `var a, b, c = 1, a, b` was already split up before reaching // here, whereas they are illegal inside a function. for _, vx := range d.Values { - un = findUndefinedV(store, last, vx, stack, defining, direct, nil) + un, directR = findUndefinedV(store, last, vx, stack, defining, direct, nil) if un != "" { + untype = false return } } @@ -4355,34 +4383,33 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ if isBlankIdentifier(tx) { panic("cannot use _ as value or type") } - // do not allow nil as type. if tx.Name == "nil" { panic("nil is not a type") } - + // sanity check. if tv := last.GetValueRef(store, tx.Name, true); tv != nil { t = tv.GetType() if dt, ok := t.(*DeclaredType); ok { if !dt.sealed { - // predefineRecursively preprocessed dependent types. + // predefineRecursively should have + // already preprocessed dependent types! panic("should not happen") } } - } else if idx, ok := UverseNode().GetLocalIndex(tx.Name); ok { + } + // set t for proper type. + if idx, ok := UverseNode().GetLocalIndex(tx.Name); ok { // uverse name path := NewValuePathUverse(idx, tx.Name) tv := Uverse().GetValueAt(nil, path) t = tv.GetType() - } else { - // yet undefined - un = tx.Name - return } case *SelectorExpr: // get package value. - un = findUndefinedV(store, last, tx.X, stack, defining, false, nil) + un, directR = findUndefinedV(store, last, tx.X, stack, defining, false, nil) if un != "" { + untype = true return } pkgName := tx.X.(*NameExpr).Name @@ -4417,20 +4444,28 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ // last2.Define(d.Name, asValue(t)) last2.Define2(true, d.Name, t, asValue(t)) d.Path = last.GetPathForName(store, d.Name) - } // END *TypeDecl - // after predefinitions, return any undefined dependencies. - un = findUndefinedT(store, last, d.Type, stack, defining, direct) + } // END if !isLocallyDefined(last2, d.Name) { + // now it is or was locally defined. + + // after predefinitions (for reasonable recursion support), + // return any undefined dependencies. + un, directR = findUndefinedAny( + store, last, d.Type, stack, defining, d.IsAlias, direct, true, nil) if un != "" { + untype = true return } + // END *TypeDecl case *FuncDecl: - un = findUndefinedT(store, last, &d.Type, stack, defining, false) + un, directR = findUndefinedT(store, last, &d.Type, stack, defining, false, false) if un != "" { + untype = true return } if d.IsMethod { - un = findUndefinedT(store, last, &d.Recv, stack, defining, false) + un, directR = findUndefinedT(store, last, &d.Recv, stack, defining, false, false) if un != "" { + untype = true return } if d.Recv.Name == "" || d.Recv.Name == blankIdentifier { @@ -4553,7 +4588,8 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ "unexpected declaration type %v", d.String())) } - return "" + // predefine complete. + return "", false, false // zero values } var reExpectedPkgName = regexp.MustCompile(`(?:^|/)([^/]+)(?:/v\d+)?$`) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index f233fe80de8..c9c2adaf391 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2101,6 +2101,7 @@ func fillEmbeddedName(ft *FieldType) { case *DeclaredType: ft.Name = ct.Name default: + // should not happen, panic("should not happen") } case *DeclaredType: diff --git a/gnovm/tests/files/circular_constant.gno b/gnovm/tests/files/circular_constant.gno index 3ca2f5b7acc..b73196ec3fb 100644 --- a/gnovm/tests/files/circular_constant.gno +++ b/gnovm/tests/files/circular_constant.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/circular_constant.gno:3:7: constant definition loop with A +// main/circular_constant.gno:3:7: invalid recursive value: A -> B -> A // TypeCheckError: // main/circular_constant.gno:3:7: initialization cycle for A; main/circular_constant.gno:3:7: A refers to B; main/circular_constant.gno:4:7: B refers to A diff --git a/gnovm/tests/files/const34.gno b/gnovm/tests/files/const34.gno index ff7a7c60725..f9043d43b3a 100644 --- a/gnovm/tests/files/const34.gno +++ b/gnovm/tests/files/const34.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const34.gno:3:7: func func(){ (const (println func(...interface {})))((const ("hey" string))) } (variable of type func()) is not constant +// main/const34.gno:3:7: func func(){ println("hey") } (variable of type func()) is not constant // TypeCheckError: // main/const34.gno:3:11: (func() literal) (value of type func()) is not constant diff --git a/gnovm/tests/files/const9.gno b/gnovm/tests/files/const9.gno index 67e3fd5cd12..c57d738d757 100644 --- a/gnovm/tests/files/const9.gno +++ b/gnovm/tests/files/const9.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/const9.gno:5:2: constant definition loop with b +// main/const9.gno:5:2: invalid recursive value: b -> c -> d -> e -> b // TypeCheckError: // main/const9.gno:6:2: initialization cycle for c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b; main/const9.gno:5:2: b refers to c; main/const9.gno:5:2: initialization cycle for b; main/const9.gno:5:2: b refers to c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b From 48675f029571b66440aa89da11904efb605313f8 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 00:05:12 -0700 Subject: [PATCH 24/83] fix all file tests --- gnovm/pkg/gnolang/preprocess.go | 4 ++-- gnovm/tests/files/type31.gno | 2 +- gnovm/tests/files/type32.gno | 2 +- gnovm/tests/files/types/add_a0.gno | 2 +- gnovm/tests/files/types/add_a1.gno | 2 +- gnovm/tests/files/types/add_e0.gno | 2 +- gnovm/tests/files/types/and_a0.gno | 2 +- gnovm/tests/files/types/and_a1.gno | 2 +- gnovm/tests/files/types/and_e0.gno | 2 +- gnovm/tests/files/types/or_a0.gno | 2 +- gnovm/tests/files/types/or_a1.gno | 2 +- gnovm/tests/files/types/or_e0.gno | 2 +- gnovm/tests/files/types/rem_a0.gno | 2 +- gnovm/tests/files/types/rem_a1.gno | 2 +- gnovm/tests/files/types/shift_d54.gno | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 19f24faa197..a52fdf01ab7 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -15,7 +15,7 @@ import ( const ( blankIdentifier = "_" - debugFind = false //true // toggle when debugging. + debugFind = false // toggle when debugging. ) // Predefine (initStaticBlocks) and partially evaluates all names @@ -3961,7 +3961,7 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin ct = elide cx.Type = constType(cx, elide) } else { - un, directR = findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) + un, directR = findUndefinedT(store, last, cx.Type, stack, defining, isalias, astype && direct) if un != "" { return } diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index 1d8173615d9..bb272a2d25e 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/type31.gno:8:10: invalid operation: mismatched types string and main.String +// main/type31.gno:8:10: invalid operation: x + y (mismatched types string and main.String) // TypeCheckError: // main/type31.gno:8:10: invalid operation: x + y (mismatched types string and String) diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index caa6ed31c5f..463dab56f98 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/type32.gno:9:11: invalid operation: mismatched types string and main.S +// main/type32.gno:9:11: invalid operation: a + (const (":" string)) + b (mismatched types string and main.S) // TypeCheckError: // main/type32.gno:9:11: invalid operation: a + ":" + b (mismatched types string and S) diff --git a/gnovm/tests/files/types/add_a0.gno b/gnovm/tests/files/types/add_a0.gno index 1796575aeb0..65901991a36 100644 --- a/gnovm/tests/files/types/add_a0.gno +++ b/gnovm/tests/files/types/add_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/add_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/add_a0.gno:5:10: invalid operation: (const (1 int)) + (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/add_a0.gno:5:10: invalid operation: int(1) + int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/add_a1.gno b/gnovm/tests/files/types/add_a1.gno index f54131dc367..4c58e008e1a 100644 --- a/gnovm/tests/files/types/add_a1.gno +++ b/gnovm/tests/files/types/add_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/add_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_a1.gno:21:10: invalid operation: (const (0 main.Error1)) + (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/add_a1.gno:21:10: invalid operation: Error1(0) + Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_e0.gno b/gnovm/tests/files/types/add_e0.gno index 8e05aff56a3..df6bb6d6de3 100644 --- a/gnovm/tests/files/types/add_e0.gno +++ b/gnovm/tests/files/types/add_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/add_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_a0.gno b/gnovm/tests/files/types/and_a0.gno index cd595f11c20..7ad33afb708 100644 --- a/gnovm/tests/files/types/and_a0.gno +++ b/gnovm/tests/files/types/and_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/and_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/and_a0.gno:5:10: invalid operation: (const (0 int)) & (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/and_a0.gno:5:10: invalid operation: int(0) & int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/and_a1.gno b/gnovm/tests/files/types/and_a1.gno index 84ad0de1692..05d52a54436 100644 --- a/gnovm/tests/files/types/and_a1.gno +++ b/gnovm/tests/files/types/and_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/and_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/and_a1.gno:21:10: invalid operation: (const (0 main.Error1)) & (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/and_a1.gno:21:10: invalid operation: Error1(0) & Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_e0.gno b/gnovm/tests/files/types/and_e0.gno index 8129563ac16..7dc46bdc524 100644 --- a/gnovm/tests/files/types/and_e0.gno +++ b/gnovm/tests/files/types/and_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/and_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_a0.gno b/gnovm/tests/files/types/or_a0.gno index 6ded1ca25f8..7bf317bdca6 100644 --- a/gnovm/tests/files/types/or_a0.gno +++ b/gnovm/tests/files/types/or_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/or_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/or_a0.gno:5:10: invalid operation: (const (0 int)) | (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/or_a0.gno:5:10: invalid operation: int(0) | int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/or_a1.gno b/gnovm/tests/files/types/or_a1.gno index d21bad7643f..46f273878a6 100644 --- a/gnovm/tests/files/types/or_a1.gno +++ b/gnovm/tests/files/types/or_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/or_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/or_a1.gno:21:10: invalid operation: (const (0 main.Error1)) | (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/or_a1.gno:21:10: invalid operation: Error1(0) | Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_e0.gno b/gnovm/tests/files/types/or_e0.gno index 759144f1885..a385c58205f 100644 --- a/gnovm/tests/files/types/or_e0.gno +++ b/gnovm/tests/files/types/or_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/or_e0.gno:23:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/rem_a0.gno b/gnovm/tests/files/types/rem_a0.gno index 7f133a19086..53cb5fb0470 100644 --- a/gnovm/tests/files/types/rem_a0.gno +++ b/gnovm/tests/files/types/rem_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/rem_a0.gno:5:10: invalid operation: mismatched types int and int8 +// main/rem_a0.gno:5:10: invalid operation: (const (1 int)) % (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/rem_a0.gno:5:10: invalid operation: int(1) % int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/rem_a1.gno b/gnovm/tests/files/types/rem_a1.gno index cebd669d6ac..53b8faedc6f 100644 --- a/gnovm/tests/files/types/rem_a1.gno +++ b/gnovm/tests/files/types/rem_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/rem_a1.gno:21:10: invalid operation: mismatched types main.Error1 and main.Error2 +// main/rem_a1.gno:21:10: invalid operation: (const (0 main.Error1)) % (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/rem_a1.gno:21:10: invalid operation: Error1(0) % Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/shift_d54.gno b/gnovm/tests/files/types/shift_d54.gno index 66fdb1963f4..3a541e30337 100644 --- a/gnovm/tests/files/types/shift_d54.gno +++ b/gnovm/tests/files/types/shift_d54.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/shift_d54.gno:8:7: invalid operation: mismatched types int32 and int +// main/shift_d54.gno:8:7: invalid operation: b + a << (const (2 uint)) (mismatched types int32 and int) // TypeCheckError: // main/shift_d54.gno:8:7: invalid operation: b + a << 2 (mismatched types int32 and int) From 6dee37a8ffdff571d3fbfefe1c01168d4b17d172 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 06:32:33 -0700 Subject: [PATCH 25/83] recursive10.gno; recursive11.gno --- gnovm/tests/files/recursive10.gno | 17 +++++++++++++++++ gnovm/tests/files/recursive11.gno | 13 +++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 gnovm/tests/files/recursive10.gno create mode 100644 gnovm/tests/files/recursive11.gno diff --git a/gnovm/tests/files/recursive10.gno b/gnovm/tests/files/recursive10.gno new file mode 100644 index 00000000000..19789fdd57b --- /dev/null +++ b/gnovm/tests/files/recursive10.gno @@ -0,0 +1,17 @@ +package main + +func A() int { return b } +func B() int { return a } + +var a = func() int { return A() }() +var b = func() int { return B() }() + +func main() { + println(a, b) +} + +// Error: +// main/recursive10.gno:3:1: loop in variable initialization: dependency trail [b B a A] circularly depends on b + +// TypeCheckError: +// main/recursive10.gno:6:5: initialization cycle for a; main/recursive10.gno:6:5: a refers to A; main/recursive10.gno:3:6: A refers to b; main/recursive10.gno:7:5: b refers to B; main/recursive10.gno:4:6: B refers to a diff --git a/gnovm/tests/files/recursive11.gno b/gnovm/tests/files/recursive11.gno new file mode 100644 index 00000000000..756796f5f22 --- /dev/null +++ b/gnovm/tests/files/recursive11.gno @@ -0,0 +1,13 @@ +package main + +var A = func() { B() } +var B = func() { A() } + +func main() { +} + +// Error: +// main/recursive11.gno:3:5: loop in variable initialization: dependency trail [B A] circularly depends on B + +// TypeCheckError: +// main/recursive11.gno:3:5: initialization cycle for A; main/recursive11.gno:3:5: A refers to B; main/recursive11.gno:4:5: B refers to A From 40e90e3ae2a4d4c679a66abc102c6e29d7e1621c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 11:47:05 -0700 Subject: [PATCH 26/83] remove spurious files from testing/base --- gnovm/stdlibs/testing/base/README.md | 4 + gnovm/stdlibs/testing/base/fuzz.gno | 284 --------------------- gnovm/stdlibs/testing/base/fuzz_test.gno | 168 ------------ gnovm/stdlibs/testing/base/random.gno | 72 ------ gnovm/stdlibs/testing/base/random_test.gno | 98 ------- 5 files changed, 4 insertions(+), 622 deletions(-) create mode 100644 gnovm/stdlibs/testing/base/README.md delete mode 100644 gnovm/stdlibs/testing/base/fuzz.gno delete mode 100644 gnovm/stdlibs/testing/base/fuzz_test.gno delete mode 100644 gnovm/stdlibs/testing/base/random.gno delete mode 100644 gnovm/stdlibs/testing/base/random_test.gno diff --git a/gnovm/stdlibs/testing/base/README.md b/gnovm/stdlibs/testing/base/README.md new file mode 100644 index 00000000000..b23d14e9da7 --- /dev/null +++ b/gnovm/stdlibs/testing/base/README.md @@ -0,0 +1,4 @@ +This package exists because we add many things into `testing` beyond Go's +`testing` module, and this creates circular dependencies in our own standard +libraries. Standard library packages like crypto/bech32 need to import +`testing/base` instead of `testing`. diff --git a/gnovm/stdlibs/testing/base/fuzz.gno b/gnovm/stdlibs/testing/base/fuzz.gno deleted file mode 100644 index 1022f2961d6..00000000000 --- a/gnovm/stdlibs/testing/base/fuzz.gno +++ /dev/null @@ -1,284 +0,0 @@ -package base - -import "strings" - -type Fuzzer interface { - InsertDeleteMutate(p float64) Fuzzer - Mutate() Fuzzer - String() string -} - -type StringFuzzer struct { - Value string - f *F -} - -func NewStringFuzzer(value string) *StringFuzzer { - return &StringFuzzer{Value: value} -} - -// Mutate changes a StringFuzzer's value by replacing a random character -// with a random ASCII character. -func (sf *StringFuzzer) Mutate() Fuzzer { - runes := []rune(sf.Value) - if len(runes) == 0 { - return sf - } - - index := randRange(0, len(runes)-1) - runes[index] = randomASCIIChar() - - return NewStringFuzzer(string(runes)) -} - -func (sf *StringFuzzer) InsertDeleteMutate(p float64) Fuzzer { - value := InsertDelete(sf.Value, p) - return NewStringFuzzer(value) -} - -func (sf *StringFuzzer) Fuzz() string { - if GenerateRandomBool(0.2) { - return InsertDelete(sf.Value, 0.1) - } - - rs := []rune(sf.Value) - lrs := len(rs) - - if lrs == 0 { - return sf.Value - } - - index := randRange(0, lrs-1) - rs[index] = randomASCIIChar() - - return string(rs) -} - -func (sf *StringFuzzer) String() string { - return sf.Value -} - -func randomASCIIChar() rune { - r := int(randRange(32, 126)) - - return rune(r) -} - -// Individual represents a single individual in the population. -type Individual struct { - Fuzzer Fuzzer - Fitness int -} - -func NewIndividual(fuzzer Fuzzer) *Individual { - return &Individual{Fuzzer: fuzzer} -} - -func (ind *Individual) calculateFitness() { - ind.Fitness = len(ind.Fuzzer.String()) -} - -// Selection selects individuals from the population based on their fitness. -// -// Use roulette wheel selection to select individuals from the population. -// ref: https://en.wikipedia.org/wiki/Fitness_proportionate_selection -func Selection(population []*Individual) []*Individual { - totalFitness := calculateTotalFitness(population) - selected := make([]*Individual, len(population)) - - for i := range selected { - selected[i] = selectIndividual(population, totalFitness) - } - - return selected -} - -func calculateTotalFitness(population []*Individual) int { - totalFitness := 0 - - for _, ind := range population { - totalFitness += ind.Fitness - } - - return totalFitness -} - -func selectIndividual(population []*Individual, totalFitness int) *Individual { - pick := randRange(0, totalFitness-1) - sum := 0 - - for _, ind := range population { - sum += ind.Fitness - if uint64(sum) > uint64(pick) { - return ind - } - } - - return nil -} - -// Crossover takes two parents and creates two children by combining their genetic material. -// -// The pivot point is chosen randomly from the length of the shortest parent. after the pivot point selected, -// the genetic material of the two parents is swapped to create the two children. -func Crossover(parent1, parent2 *Individual) (*Individual, *Individual) { - p1Runes := []rune(parent1.Fuzzer.String()) - p2Runes := []rune(parent2.Fuzzer.String()) - - p1Len := len(p1Runes) - p2Len := len(p2Runes) - - point := 0 - if p1Len >= p2Len { - point = int(randRange(0, p2Len-1)) - } else { - point = int(randRange(0, p1Len-1)) - } - - child1 := append(append([]rune{}, p1Runes[:point]...), p2Runes[point:]...) - child2 := append(append([]rune{}, p2Runes[:point]...), p1Runes[point:]...) - - updatedIdv1 := NewIndividual(NewStringFuzzer(string(child1))) - updatedIdv2 := NewIndividual(NewStringFuzzer(string(child2))) - - return updatedIdv1, updatedIdv2 -} - -func (ind *Individual) Mutate() { - ind.Fuzzer = ind.Fuzzer.Mutate() -} - -// InsertDelete randomly inserts or deletes a character from a string. -func InsertDelete(s string, p float64) string { - rr := []rune(s) - l := len(rr) - - // Insert - if GenerateRandomBool(p) { - pos := randRange(0, l-1) - rr = append(rr, 0) - - copy(rr[pos+1:], rr[pos:]) - - char := randomASCIIChar() - rr[pos] = char - } else { - if l == 0 { - return s - } - - pos := randRange(0, l-1) - rr = append(rr[:pos], rr[pos+1:]...) - } - - return string(rr) -} - -type F struct { - corpus []string - failed bool // Indicates whether the fuzzing has encountered a failure. - msgs []string // Stores log messages for reporting. - iters int // Number of iterations to run the fuzzing process. TODO: CLI flag to set this. -} - -// Runner is a type for the target function to fuzz. -type Runner func(*T, ...any) - -// Fuzz applies the fuzzing process to the target function. -func (f *F) Fuzz(run Runner, iter int) { - f.evolve(iter) - - for _, input := range f.corpus { - args := make([]any, len(f.corpus)) - for i := range args { - args[i] = input - } - - run(nil, args...) - } -} - -// Add adds test values to initialize the corpus. -func (f *F) Add(values ...any) []Fuzzer { - fuzzers := make([]Fuzzer, len(values)) - - for i, v := range values { - str, ok := v.(string) - if !ok { - continue - } - f.corpus = append(f.corpus, str) - fuzzers[i] = &StringFuzzer{Value: str} - } - - return fuzzers -} - -func (f *F) evolve(generations int) { - population := make([]*Individual, len(f.corpus)) - for i, c := range f.corpus { - population[i] = &Individual{Fuzzer: &StringFuzzer{Value: c, f: f}} - } - - for _, ind := range population { - ind.calculateFitness() - } - - for gen := 0; gen < generations; gen++ { - population = Selection(population) - newPopulation := make([]*Individual, 0, len(population)) - - for i := 0; i < len(population); i += 2 { - if i+1 < len(population) { - child1, child2 := Crossover(population[i], population[i+1]) - newPopulation = append(newPopulation, child1, child2) - continue - } - - newPopulation = append(newPopulation, population[i]) - } - - var bestFitness int - - for _, ind := range newPopulation { - if GenerateRandomBool(0.2) { - ind.Mutate() - } - - if GenerateRandomBool(0.1) { - ind.Fuzzer = ind.Fuzzer.InsertDeleteMutate(0.3) - } - - ind.calculateFitness() - - if ind.Fitness > bestFitness { - bestFitness = ind.Fitness - } - } - - population = newPopulation - } - - f.corpus = make([]string, len(population)) - for i, ind := range population { - f.corpus[i] = ind.Fuzzer.String() - } -} - -// Fail marks the function as having failed bur continue execution. -func (f *F) Fail() { - f.failed = true -} - -// Fatal is equivalent to Log followed by FailNow. -// It logs the message and marks the fuzzing as failed. -func (f *F) Fatal(args ...any) { - var sb strings.Builder - - for _, arg := range args { - sb.WriteString(arg.(string)) - } - - f.msgs = append(f.msgs, sb.String()) - f.Fail() -} diff --git a/gnovm/stdlibs/testing/base/fuzz_test.gno b/gnovm/stdlibs/testing/base/fuzz_test.gno deleted file mode 100644 index 6464b0d6d38..00000000000 --- a/gnovm/stdlibs/testing/base/fuzz_test.gno +++ /dev/null @@ -1,168 +0,0 @@ -package base - -import "strings" - -func TestMutate(t *T) { - originalValue := "Hello" - fuzzer := StringFuzzer{Value: originalValue} - - newFuzzer := fuzzer.Mutate().(*StringFuzzer) - - if newFuzzer.Value == originalValue { - t.Errorf("Mutate did not change the string: got %v, want different from %v", newFuzzer.Value, originalValue) - } - - if len(newFuzzer.Value) != len(originalValue) { - t.Errorf("Mutated string has different length: got %s (len=%v), want %s (len=%v)", newFuzzer.Value, len(newFuzzer.Value), originalValue, len(originalValue)) - } -} - -func TestSelection(t *T) { - tests := []struct { - name string - population []*Individual - }{ - { - name: "Empty population", - population: []*Individual{}, - }, - { - name: "Uniform fitness", - population: []*Individual{ - {Fitness: 10}, - {Fitness: 10}, - {Fitness: 10}, - }, - }, - { - name: "Different fitness", - population: []*Individual{ - {Fitness: 5}, - {Fitness: 15}, - {Fitness: 10}, - }, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *T) { - selected := Selection(tc.population) - if len(selected) != len(tc.population) { - t.Errorf("Expected selected length to be %d, got %d", len(tc.population), len(selected)) - } - }) - } -} - -func TestCrossover(t *T) { - parent1 := NewIndividual(&StringFuzzer{Value: "foobar"}) - parent2 := NewIndividual(&StringFuzzer{Value: "bazbiz"}) - - var child1, child2 *Individual - for i := 0; i < 100; i++ { - child1, child2 = Crossover(parent1, parent2) - } - - if child1.Fuzzer.String() == "foobar" || child2.Fuzzer.String() == "bazbiz" { - t.Errorf("Crossover did not modify children correctly, got %s and %s", child1.Fuzzer.String(), child2.Fuzzer.String()) - } -} - -func Test_StringManipulation(t *T) { - f := &F{ - corpus: []string{"hello", "world", "foo", "bar"}, - } - - f.evolve(30) - - if len(f.corpus) != 4 { - t.Fatalf("corpus length is %d, want 4", len(f.corpus)) - } - - for i, c := range f.corpus { - if c == "" { - t.Fatalf("corpus[%d] is empty", i) - } - - if len(c) < 3 { - t.Fatalf("corpus[%d] is too short: %s", i, c) - } - - if f.corpus[0] == "hello" { - t.Fatalf("corpus[0] is still the same: %s", f.corpus[0]) - } - - if f.corpus[1] == "world" { - t.Fatalf("corpus[1] is still the same: %s", f.corpus[1]) - } - - if f.corpus[2] == "foo" { - t.Fatalf("corpus[2] is still the same: %s", f.corpus[2]) - } - - if f.corpus[3] == "bar" { - t.Fatalf("corpus[3] is still the same: %s", f.corpus[3]) - } - - } -} - -func TestFuzz(t *T) { - f := F{} - f.Add("hello", "world", "foo") - f.Fuzz(func(t *T, inputs ...any) { - for _, input := range inputs { - strInput, ok := input.(string) - if !ok { - t.Errorf("Type mismatch, expected a string but got %T", input) - continue - } - - words := strings.Fields(strInput) - if len(words) == 0 { - t.Errorf("Expected non-empty input") - } - } - }, 15) - - if len(f.corpus) == 0 { - t.Fatalf("Fuzzing corpus is empty after testing") - } - - if len(f.corpus) > 3 { - t.Fatalf("Fuzzing corpus has more than 3 elements: %v", f.corpus) - } - - for _, c := range f.corpus { - if c == "hello" || c == "world" || c == "foo" { - t.Fatalf("Fuzzing corpus still contains the original elements: %v", f.corpus) - } - } -} - -func TestF_Fail(t *T) { - f := F{} - f.Fail() - - if !f.failed { - t.Errorf("Fail did not set the failed flag.") - } -} - -func TestF_Fatal(t *T) { - f := F{} - testMessage := "test failure message" - f.Fatal(testMessage) - - if !f.failed { - t.Errorf("Fatal did not set the failed flag.") - } - - if len(f.msgs) != 1 { - t.Fatalf("Fatal did not set the message correctly: got %v, want %v", f.msgs, testMessage) - } - - if !strings.Contains(f.msgs[0], testMessage) { - t.Errorf("Fatal did not set the message correctly: got %v, want %v", f.msgs[0], testMessage) - } -} diff --git a/gnovm/stdlibs/testing/base/random.gno b/gnovm/stdlibs/testing/base/random.gno deleted file mode 100644 index 8e46a6ab0f7..00000000000 --- a/gnovm/stdlibs/testing/base/random.gno +++ /dev/null @@ -1,72 +0,0 @@ -package base - -import "math" - -// Internal state for the random number generator. -var x uint64 = 42 - -// UniformRand generates a uniformly distributed random number. -// It uses the linear congrential generator method to produce the random number. -// and the result is in the range from 0 to m-1. here, m is 32768. -// To produce random number in [0, m-1], repeat this method as many times as needed. -// [1] https://en.wikipedia.org/wiki/Linear_congruential_generator -func UniformRand() uint64 { - var a uint64 = 950213 - var c uint64 = 12345 - var m uint64 = 32768 - x = x*a + c - return (x >> 16) % m -} - -// _srand function sets the seed for the random number generator. -// This function provides an initial starting point for the sequence of random numbers. -func _srand(seed int64) { - x = uint64(seed) -} - -// nrand function generates a number approximating a normal distribution[1]. -// It uses the Central Limit Theorem[2] by summing multiple uniformly distributed random numbers -// to approximate a normal distribution. -// -// y = Sum(k=1, K) (x_k - K/2) / sqrt(K/12) -// -// Here, K is some integer ans x_k are uniformly distributed numbers, -// even for K as small as 10, the approximation is quite good. -// [1] https://en.wikipedia.org/wiki/Normal_distribution -// [2] https://en.wikipedia.org/wiki/Central_limit_theorem -func nrand() float64 { - var i, K uint64 = 0, 10 - var m uint64 = 32768 - var y float64 = 0 - - for i = 0; i < K; i++ { - y += float64(UniformRand()) / float64(m) - } - y = (y - float64(K)/2) / math.Sqrt(float64(K)/12) - return y -} - -// randRange generates a random integer between min and max (inclusive). -// This function leverages the UniformRand function to generate a random number in a specified range. -// Note: max should be greater than min. -func randRange(min, max int) uint64 { - _min := uint64(min) - _max := uint64(max) - if _min >= _max { - return _min - } - - rangeSize := _max - _min + 1 - // adjust UniformRand to fit into our range. - return _min + (UniformRand() % rangeSize) -} - -func GenerateRandomBool(bias float64) bool { - // Modify to use fuzz's random function for generating boolean with bias - if bias < 0 || bias > 1 { - panic("bias should be in the range [0, 1]") - } - // Convert fuzz's normalized range random float [-1, 1] to [0, 1] - res := (nrand() + 1) / 2 - return res > bias -} diff --git a/gnovm/stdlibs/testing/base/random_test.gno b/gnovm/stdlibs/testing/base/random_test.gno deleted file mode 100644 index bdb4948a13c..00000000000 --- a/gnovm/stdlibs/testing/base/random_test.gno +++ /dev/null @@ -1,98 +0,0 @@ -package base - -import ( - "math" - "time" -) - -func updateSeed() { - seed := time.Now().UnixNano() - _srand(seed) -} - -func Test_UniformRand(t *T) { - valueMap := make(map[uint64]int) - maxIter := 1000 - - for i := 0; i < maxIter; i++ { - result := UniformRand() - - if result < 0 || result >= 32768 { - t.Errorf("rand() = %v, want in range [0, 32767]", result) - } - - if _, ok := valueMap[result]; ok { - valueMap[result]++ - } else { - valueMap[result] = 1 - } - } - - lvm := len(valueMap) - if lvm > maxIter || lvm == 0 { - t.Errorf("len(valueMap) = %v, want <= %v", lvm, maxIter) - } -} - -func Test_nrand(t *T) { - sum := 0.0 - for i := 0; i < 1000; i++ { - result := nrand() - sum += result - } - avg := sum / float64(1000) - - // The value returned by nrand() should be close to 0 - // on average for large sample sizes. - // The expectation of the standard deviation should be - // close to 1 for large sample sizes. - if math.Abs(avg) > 0.1 { // can be adjusted based on sample size - t.Errorf("nrand() = %v, want in range [-0.1, 0.1]", avg) - } -} - -func Test_GenerateRandomBool(t *T) { - updateSeed() - - for _, bias := range []float64{0, 0.5, 1} { - trueCount, falseCount := 0, 0 - sampleSize := 1000 - - for i := 0; i < sampleSize; i++ { - result := GenerateRandomBool(bias) - if result { - trueCount++ - } else { - falseCount++ - } - } - - if trueCount == 0 || falseCount == 0 { - t.Errorf("Bias = %v, trueCount = %v, falseCount = %v, want both > 0", bias, trueCount, falseCount) - } - - if bias < 0 || bias > 1 { - t.Errorf("Bias = %v, want in range [0, 1]", bias) - } - } -} - -func TestRandRange(t *T) { - nums := make(map[uint64]int) - for i := 0; i < 1000; i++ { - res := randRange(0, 10) - if res < 0 || res > 10 { - t.Errorf("gerandRangenerateRange() = %v, want in range [0, 9]", res) - } - - if _, ok := nums[res]; ok { - nums[res]++ - } else { - nums[res] = 1 - } - } - - if len(nums) != 11 { - t.Errorf("len(nums) = %v, want in range [0, 10]", len(nums)) - } -} From 4f970ec0c9c40a6eaf20f3f616b74043edc4904a Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 11:50:50 -0700 Subject: [PATCH 27/83] ... --- gnovm/stdlibs/testing/base/match.gno | 2 +- gnovm/stdlibs/testing/base/testing.gno | 2 +- gnovm/stdlibs/testing/base/testing.go | 2 +- .../stdlibs/testing/base/native_testing.gno | 7 +++++ .../stdlibs/testing/base/native_testing.go | 28 +++++++++++++++++++ 5 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 gnovm/tests/stdlibs/testing/base/native_testing.gno create mode 100644 gnovm/tests/stdlibs/testing/base/native_testing.go diff --git a/gnovm/stdlibs/testing/base/match.gno b/gnovm/stdlibs/testing/base/match.gno index 25d1da808c0..2475f854f64 100644 --- a/gnovm/stdlibs/testing/base/match.gno +++ b/gnovm/stdlibs/testing/base/match.gno @@ -1,4 +1,4 @@ -package base +package testing // Most of the code in this file is extracted from golang's src/testing/match.go. // diff --git a/gnovm/stdlibs/testing/base/testing.gno b/gnovm/stdlibs/testing/base/testing.gno index 7466af1fce2..30f3236f178 100644 --- a/gnovm/stdlibs/testing/base/testing.gno +++ b/gnovm/stdlibs/testing/base/testing.gno @@ -1,5 +1,5 @@ // Shim for Go's "testing" package to support minimal testing types. -package base +package testing import ( "fmt" diff --git a/gnovm/stdlibs/testing/base/testing.go b/gnovm/stdlibs/testing/base/testing.go index 520f333b563..16310a2f648 100644 --- a/gnovm/stdlibs/testing/base/testing.go +++ b/gnovm/stdlibs/testing/base/testing.go @@ -1,4 +1,4 @@ -package base +package testing import ( "github.com/gnolang/gno/gnovm/pkg/gnolang" diff --git a/gnovm/tests/stdlibs/testing/base/native_testing.gno b/gnovm/tests/stdlibs/testing/base/native_testing.gno new file mode 100644 index 00000000000..94c5dbb6f89 --- /dev/null +++ b/gnovm/tests/stdlibs/testing/base/native_testing.gno @@ -0,0 +1,7 @@ +package testing + +func unixNano() int64 + +func matchString(pat, str string) (bool, string) + +func recoverWithStacktrace() (interface{}, string) diff --git a/gnovm/tests/stdlibs/testing/base/native_testing.go b/gnovm/tests/stdlibs/testing/base/native_testing.go new file mode 100644 index 00000000000..0be21b614f8 --- /dev/null +++ b/gnovm/tests/stdlibs/testing/base/native_testing.go @@ -0,0 +1,28 @@ +package testing + +import ( + "regexp" + "time" + + "github.com/gnolang/gno/gnovm/pkg/gnolang" +) + +func X_unixNano() int64 { + return time.Now().UnixNano() +} + +func X_matchString(pat, str string) (bool, string) { + matchRe, err := regexp.Compile(pat) + if err != nil { + return false, err.Error() + } + return matchRe.MatchString(str), "" +} + +func X_recoverWithStacktrace(m *gnolang.Machine) (gnolang.TypedValue, string) { + exception := m.Recover() + if exception == nil { + return gnolang.TypedValue{}, "" + } + return exception.Value, exception.Stacktrace.String() +} From 36e2213cc14359827d49205886229940647b7906 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 11:52:26 -0700 Subject: [PATCH 28/83] ... --- gnovm/stdlibs/testing/base/match.gno | 2 +- gnovm/stdlibs/testing/base/testing.gno | 2 +- gnovm/stdlibs/testing/base/testing.go | 2 +- gnovm/tests/stdlibs/testing/base/native_testing.gno | 2 +- gnovm/tests/stdlibs/testing/base/native_testing.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gnovm/stdlibs/testing/base/match.gno b/gnovm/stdlibs/testing/base/match.gno index 2475f854f64..25d1da808c0 100644 --- a/gnovm/stdlibs/testing/base/match.gno +++ b/gnovm/stdlibs/testing/base/match.gno @@ -1,4 +1,4 @@ -package testing +package base // Most of the code in this file is extracted from golang's src/testing/match.go. // diff --git a/gnovm/stdlibs/testing/base/testing.gno b/gnovm/stdlibs/testing/base/testing.gno index 30f3236f178..7466af1fce2 100644 --- a/gnovm/stdlibs/testing/base/testing.gno +++ b/gnovm/stdlibs/testing/base/testing.gno @@ -1,5 +1,5 @@ // Shim for Go's "testing" package to support minimal testing types. -package testing +package base import ( "fmt" diff --git a/gnovm/stdlibs/testing/base/testing.go b/gnovm/stdlibs/testing/base/testing.go index 16310a2f648..520f333b563 100644 --- a/gnovm/stdlibs/testing/base/testing.go +++ b/gnovm/stdlibs/testing/base/testing.go @@ -1,4 +1,4 @@ -package testing +package base import ( "github.com/gnolang/gno/gnovm/pkg/gnolang" diff --git a/gnovm/tests/stdlibs/testing/base/native_testing.gno b/gnovm/tests/stdlibs/testing/base/native_testing.gno index 94c5dbb6f89..12bda0836e8 100644 --- a/gnovm/tests/stdlibs/testing/base/native_testing.gno +++ b/gnovm/tests/stdlibs/testing/base/native_testing.gno @@ -1,4 +1,4 @@ -package testing +package base func unixNano() int64 diff --git a/gnovm/tests/stdlibs/testing/base/native_testing.go b/gnovm/tests/stdlibs/testing/base/native_testing.go index 0be21b614f8..c627c46b33e 100644 --- a/gnovm/tests/stdlibs/testing/base/native_testing.go +++ b/gnovm/tests/stdlibs/testing/base/native_testing.go @@ -1,4 +1,4 @@ -package testing +package base import ( "regexp" From fe061b57856dd6e4397368f9b78ebd61053018bf Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 11:53:19 -0700 Subject: [PATCH 29/83] ... --- gnovm/stdlibs/generated.go | 83 +------------------------------- gnovm/tests/stdlibs/generated.go | 83 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 82 deletions(-) diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index a9d27d9a303..a474f75d622 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -13,7 +13,6 @@ import ( libs_runtime "github.com/gnolang/gno/gnovm/stdlibs/runtime" libs_std "github.com/gnolang/gno/gnovm/stdlibs/std" libs_sys_params "github.com/gnolang/gno/gnovm/stdlibs/sys/params" - libs_testing "github.com/gnolang/gno/gnovm/stdlibs/testing" libs_testing_base "github.com/gnolang/gno/gnovm/stdlibs/testing/base" libs_time "github.com/gnolang/gno/gnovm/stdlibs/time" ) @@ -1135,86 +1134,6 @@ var nativeFuncs = [...]NativeFunc{ p0, p1, p2, p3) }, }, - { - "testing", - "unixNano", - []gno.FieldTypeExpr{}, - []gno.FieldTypeExpr{ - {NameExpr: *gno.Nx("r0"), Type: gno.X("int64")}, - }, - false, - func(m *gno.Machine) { - r0 := libs_testing.X_unixNano() - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) - }, - }, - { - "testing", - "recoverWithStacktrace", - []gno.FieldTypeExpr{}, - []gno.FieldTypeExpr{ - {NameExpr: *gno.Nx("r0"), Type: gno.AnyT()}, - {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, - }, - false, - func(m *gno.Machine) { - r0, r1 := libs_testing.X_recoverWithStacktrace() - - m.PushValue(r0) - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r1).Elem(), - )) - }, - }, - { - "testing", - "matchString", - []gno.FieldTypeExpr{ - {NameExpr: *gno.Nx("p0"), Type: gno.X("string")}, - {NameExpr: *gno.Nx("p1"), Type: gno.X("string")}, - }, - []gno.FieldTypeExpr{ - {NameExpr: *gno.Nx("r0"), Type: gno.X("bool")}, - {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, - }, - false, - func(m *gno.Machine) { - b := m.LastBlock() - var ( - p0 string - rp0 = reflect.ValueOf(&p0).Elem() - p1 string - rp1 = reflect.ValueOf(&p1).Elem() - ) - - tv0 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV - tv0.DeepFill(m.Store) - gno.Gno2GoValue(tv0, rp0) - tv1 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV - tv1.DeepFill(m.Store) - gno.Gno2GoValue(tv1, rp1) - - r0, r1 := libs_testing.X_matchString(p0, p1) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r1).Elem(), - )) - }, - }, { "testing/base", "unixNano", @@ -1403,9 +1322,9 @@ var initOrder = [...]string{ "runtime", "std", "sys/params", + "testing/base", "time", "testing", - "testing/base", "unicode/utf16", } diff --git a/gnovm/tests/stdlibs/generated.go b/gnovm/tests/stdlibs/generated.go index d263a3a1863..c6ba02b90c2 100644 --- a/gnovm/tests/stdlibs/generated.go +++ b/gnovm/tests/stdlibs/generated.go @@ -11,6 +11,7 @@ import ( testlibs_os "github.com/gnolang/gno/gnovm/tests/stdlibs/os" testlibs_std "github.com/gnolang/gno/gnovm/tests/stdlibs/std" testlibs_testing "github.com/gnolang/gno/gnovm/tests/stdlibs/testing" + testlibs_testing_base "github.com/gnolang/gno/gnovm/tests/stdlibs/testing/base" testlibs_unicode "github.com/gnolang/gno/gnovm/tests/stdlibs/unicode" ) @@ -667,6 +668,88 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "testing/base", + "unixNano", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("int64")}, + }, + false, + func(m *gno.Machine) { + r0 := testlibs_testing_base.X_unixNano() + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + }, + }, + { + "testing/base", + "matchString", + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("p0"), Type: gno.X("string")}, + {NameExpr: *gno.Nx("p1"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("bool")}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + false, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() + ) + + tv0 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV + tv0.DeepFill(m.Store) + gno.Gno2GoValue(tv0, rp0) + tv1 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV + tv1.DeepFill(m.Store) + gno.Gno2GoValue(tv1, rp1) + + r0, r1 := testlibs_testing_base.X_matchString(p0, p1) + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, + { + "testing/base", + "recoverWithStacktrace", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.AnyT()}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + true, + func(m *gno.Machine) { + r0, r1 := testlibs_testing_base.X_recoverWithStacktrace( + m, + ) + + m.PushValue(r0) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, { "unicode", "IsPrint", From 64b048a61a5a851609cc6c8f0fa67a1a1c8d3bfb Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 12:03:47 -0700 Subject: [PATCH 30/83] ... --- gnovm/cmd/gno/test.go | 20 ++-- gnovm/cmd/gno/tool_lint.go | 129 +++++++------------------- gnovm/pkg/gnolang/gotypecheck.go | 11 ++- gnovm/pkg/gnolang/machine.go | 29 +----- gnovm/pkg/gnolang/nodes.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 8 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 34 ++++--- gnovm/pkg/gnolang/type_check.go | 2 +- gnovm/pkg/test/imports.go | 7 +- 9 files changed, 77 insertions(+), 165 deletions(-) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 1c1f02096a4..f62422d05ba 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -169,7 +169,6 @@ func (c *testCmd) RegisterFlags(fs *flag.FlagSet) { } func execTest(cmd *testCmd, args []string, io commands.IO) error { - // Default to current directory if no args provided if len(args) == 0 { args = []string{"."} @@ -245,17 +244,16 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { var didPanic, didError bool startedAt := time.Now() didPanic = catchPanic(pkg.Dir, pkgPath, io.Err(), func() { - //XXX why would we skip type-checking for drafts? - //if modfile == nil || !modfile.Draft { - _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore) - if errs != nil { - didError = true - io.ErrPrintln(errs) - return + if modfile == nil || !modfile.Draft { + _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore) + if errs != nil { + didError = true + io.ErrPrintln(errs) + return + } + } else if cmd.verbose { + io.ErrPrintfln("%s: module is draft, skipping type check", pkgPath) } - //} else if cmd.verbose { - // io.ErrPrintfln("%s: module is draft, skipping type check", pkgPath) - //} errs = test.Test(mpkg, pkg.Dir, opts) if errs != nil { didError = true diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index d8560c7b3c6..982c917ff72 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -29,13 +29,6 @@ import ( /* Linting. Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). - - XXX Currently the linter only supports linting directories. In order to - support linting individual files, we need to refactor this code to work - with mempackages, not dirs, and cmd/gno/util.go needs to be refactored - to return mempackages rather than dirs. Commands like `gno lint a.gno - b.gno` should create a temporary package from just those files. We - could also load mempackages lazily for memory efficiency. */ type processedPackage struct { @@ -129,17 +122,23 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { ) ppkgs := map[string]processedPackage{} - // TODO print progress when verbose. - // fmt.Println("linting directories...", dirs) + if cmd.verbose { + io.ErrPrintfln("flinting directories: %v", dirs) + } //---------------------------------------- - // STAGE 1: + // STAGE 1: Lint. for _, dir := range dirs { - // TODO print progress when verbose. - // fmt.Printf("linting %q\n", dir) if cmd.verbose { - io.ErrPrintln(dir) + io.ErrPrintfln("linting %q", dir) } + // XXX Currently the linter only supports linting directories. + // In order to support linting individual files, we need to + // refactor this code to work with mempackages, not dirs, and + // cmd/gno/util.go needs to be refactored to return mempackages + // rather than dirs. Commands like `gno lint a.gno b.gno` + // should create a temporary package from just those files. We + // could also load mempackages lazily for memory efficiency. info, err := os.Stat(dir) if err == nil && !info.IsDir() { dir = filepath.Dir(dir) @@ -188,8 +187,6 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Perform imports using the parent store. - // XXX "lintImportError" is obscure, try to - // find the cause as another lint*Error? if err := test.LoadImports(ts, mpkg); err != nil { io.ErrPrintln(issueFromError( dir, pkgPath, err, lintImportError).String()) @@ -206,13 +203,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // These are Go types. var pn *gno.PackageNode - var gopkg *types.Package - var gofset *token.FileSet - var gofs, _gofs, tgofs []*ast.File var errs error - if false { - println(gopkg, "is not used") - } // Run type checking // STEP 2: ParseGnoMod() @@ -224,49 +215,37 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - //XXX why would we skip type-checking for drafts? - //if !mod.Draft { - gopkg, gofset, gofs, _gofs, tgofs, errs = - lintTypeCheck(io, dir, mpkg, gs) - if errs != nil { - // io.ErrPrintln(errs) already printed. - hasError = true - return + if !mod.Draft { + _, _, _, _, _, errs = lintTypeCheck(io, dir, mpkg, gs) + if errs != nil { + // io.ErrPrintln(errs) printed above. + hasError = true + return + } + } else if cmd.verbose { + io.ErrPrintfln("%s: module is draft, skipping type check", dir) } - //} else if cmd.verbose { - // io.ErrPrintfln("%s: module is draft, skipping type check", dir) - //} // STEP 4: Prepare*() // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) defer tm.Release() - // Prepare Go AST for preprocessing. - if mod.GetGno() == "0.0" { - allgofs := append(gofs, _gofs...) - allgofs = append(allgofs, tgofs...) - errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) - if errs != nil { - io.ErrPrintln(errs) - hasError = true - return // Prepare must succeed. - } - } - // STEP 5: re-parse // Gno parse source fileset and test filesets. - all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + _, fset, _tests, ftests := sourceAndTestFileset(mpkg) // STEP 6: PreprocessFiles() // Preprocess fset files (w/ some _test.gno). pn, _ = tm.PreprocessFiles( mpkg.Name, mpkg.Path, fset, false, false) + // STEP 6: PreprocessFiles() // Preprocess _test files (all _test.gno). for _, fset := range _tests { tm.PreprocessFiles( mpkg.Name, mpkg.Path, fset, false, false) } + // STEP 6: PreprocessFiles() // Preprocess _filetest.gno files. for _, fset := range ftests { tm.PreprocessFiles( @@ -275,18 +254,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Record results. ppkgs[dir] = processedPackage{ - mpkg, fset, pn, _tests, ftests} - - // STEP 7: FindXforms(): - // FindXforms for all files if outdated. - if mod.GetGno() == "0.0" { - // Use the preprocessor to collect the - // transformations needed to be done. - // They are collected in - // pn.GetAttribute("XREALMFORM") - for _, fn := range all.Files { - gno.FindXformsGno0p9(gs, pn, fn) - } + mpkg, fset, pn, _tests, ftests, } }) if didPanic { @@ -298,36 +266,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } //---------------------------------------- - // STAGE 2: Transpile to Gno 0.9 - // Must be a separate stage because dirs depend on each other. - for _, dir := range dirs { - ppkg, ok := ppkgs[dir] - if !ok { - // XXX fix this; happens when linting a file. - // XXX see comment on top of this file. - panic("missing package; gno lint currently only supports directories.") - } - mpkg, pn := ppkg.mpkg, ppkg.pn - - // If gno version is already 0.9, skip. - mod, err := gno.ParseCheckGnoMod(mpkg) - if mod.GetGno() == "0.9" { // XXX - continue - } - - // STEP 8 & 9: gno.TranspileGno0p9() Part 1 & 2 - xforms1, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XFORMS).(map[string]struct{}) - err = gno.TranspileGno0p9(mpkg, dir, xforms1) - if err != nil { - return err - } - } - if hasError { - return commands.ExitCodeError(1) - } - - //---------------------------------------- - // STAGE 3: Write. + // STAGE 2: Write. // Must be a separate stage to prevent partial writes. for _, dir := range dirs { ppkg, ok := ppkgs[dir] @@ -348,20 +287,22 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). // Prints and returns errors. Panics upon an unexpected error. func lintTypeCheck( + // Args: io commands.IO, dir string, mpkg *std.MemPackage, - testStore gno.Store, -) ( + testStore gno.Store) ( + // Results: gopkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, - lerr error) { + lerr error, +) { + //---------------------------------------- // gno.TypeCheckMemPackage(mpkg, testStore) var tcErrs error - gopkg, gofset, gofs, _gofs, tgofs, tcErrs = - gno.TypeCheckMemPackage(mpkg, testStore) + gopkg, gofset, gofs, _gofs, tgofs, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore) // Print errors, and return the first unexpected error. errors := multierr.Errors(tcErrs) @@ -412,8 +353,8 @@ func lintTypeCheck( // own file set. // - ftests: *_filetest.gno file tests, each in their own file set. func sourceAndTestFileset(mpkg *std.MemPackage) ( - all, fset *gno.FileSet, _tests, ftests []*gno.FileSet) { - + all, fset *gno.FileSet, _tests, ftests []*gno.FileSet, +) { all = &gno.FileSet{} fset = &gno.FileSet{} for _, mfile := range mpkg.Files { diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 4f87d69fccf..56316760f34 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -30,7 +30,8 @@ type MemPackageGetter interface { // // The syntax checking is performed entirely using Go's go/types package. func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( - pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { + pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, +) { var gimp *gnoImporter gimp = &gnoImporter{ pkgPath: mpkg.Path, @@ -95,7 +96,7 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ gimp.cache[pkgPath] = gnoImporterResult{err: err} return nil, err } - var pmode = ParseModeProduction // don't parse test files for imports... + pmode := ParseModeProduction // don't parse test files for imports... if gimp.pkgPath == pkgPath { // ...unless importing self from a *_test.gno // file with package name xxx_test. @@ -122,8 +123,8 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ // ParseModeProduction when type-checking imports. // - strict: If true errors on gno.mod version mismatch. func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMode, strict bool) ( - pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { - + pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, +) { // See adr/pr4264_lint_transpile.md // STEP 2: Check gno.mod version. if strict { @@ -162,7 +163,7 @@ type realm interface{} // shim const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var gmgof, err = parser.ParseFile( + gmgof, err := parser.ParseFile( gofset, path.Join(mpkg.Path, file.Name), file.Body, diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 91a56389ef6..3ebf7c23530 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -561,7 +561,6 @@ func (m *Machine) runFileDecls(withOverrides bool, fns ...*FileNode) []TypedValu if debug { debug.Printf("PREPROCESSED FILE: %v\n", fn) } - // fmt.Println("PREPROCESSED", fn) // After preprocessing, save blocknodes to store. SaveBlockNodes(m.Store, fn) // Make block for fn. @@ -2339,7 +2338,6 @@ func (m *Machine) String() string { if m == nil { return "Machine:nil" } - // Calculate some reasonable total length to avoid reallocation // Assuming an average length of 32 characters per string var ( @@ -2350,43 +2348,31 @@ func (m *Machine) String() string { obsLength = len(m.Blocks) * 32 fsLength = len(m.Frames) * 32 exceptionsLength = m.Exception.NumExceptions() * 32 - - totalLength = vsLength + ssLength + xsLength + bsLength + obsLength + fsLength + exceptionsLength + totalLength = vsLength + ssLength + xsLength + bsLength + obsLength + fsLength + exceptionsLength ) - var sb strings.Builder builder := &sb // Pointer for use in fmt.Fprintf. builder.Grow(totalLength) - fmt.Fprintf(builder, "Machine:\n Stage: %v\n Op: %v\n Values: (len: %d)\n", m.Stage, m.Ops[:m.NumOps], m.NumValues) - for i := m.NumValues - 1; i >= 0; i-- { fmt.Fprintf(builder, " #%d %v\n", i, m.Values[i]) } - builder.WriteString(" Exprs:\n") - for i := len(m.Exprs) - 1; i >= 0; i-- { fmt.Fprintf(builder, " #%d %v\n", i, m.Exprs[i]) } - builder.WriteString(" Stmts:\n") - for i := len(m.Stmts) - 1; i >= 0; i-- { fmt.Fprintf(builder, " #%d %v\n", i, m.Stmts[i]) } - builder.WriteString(" Blocks:\n") - for i := len(m.Blocks) - 1; i > 0; i-- { b := m.Blocks[i] if b == nil { continue } - gen := builder.Len()/3 + 1 gens := "@" // strings.Repeat("@", gen) - if pv, ok := b.Source.(*PackageNode); ok { // package blocks have too much, so just // print the pkgpath. @@ -2395,7 +2381,6 @@ func (m *Machine) String() string { bsi := b.StringIndented(" ") fmt.Fprintf(builder, " %s(%d) %s\n", gens, gen, bsi) } - // Update b switch bp := b.Parent.(type) { case nil: @@ -2409,16 +2394,12 @@ func (m *Machine) String() string { panic("should not happen") } } - builder.WriteString(" Blocks (other):\n") - for i := len(m.Blocks) - 2; i >= 0; i-- { b := m.Blocks[i] - if b == nil || b.Source == nil { continue } - if _, ok := b.Source.(*PackageNode); ok { break // done, skip *PackageNode. } else { @@ -2426,22 +2407,17 @@ func (m *Machine) String() string { b.StringIndented(" ")) } } - builder.WriteString(" Frames:\n") - for i := len(m.Frames) - 1; i >= 0; i-- { fmt.Fprintf(builder, " #%d %s\n", i, m.Frames[i]) } - if m.Realm != nil { fmt.Fprintf(builder, " Realm:\n %s\n", m.Realm.Path) } - if m.Exception != nil { builder.WriteString(" Exception:\n") fmt.Fprintf(builder, " %s\n", m.Exception.Sprint(m)) } - return builder.String() } @@ -2449,16 +2425,13 @@ func (m *Machine) ExceptionStacktrace() string { if m.Exception == nil { return "" } - var builder strings.Builder - last := m.Exception first := m.Exception var numPrevious int for ; first.Previous != nil; first = first.Previous { numPrevious++ } - builder.WriteString(first.StringWithStacktrace(m)) if numPrevious >= 2 { fmt.Fprintf(&builder, "... %d panic(s) elided ...\n", numPrevious-1) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index da892791a21..5f7646fdd07 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -191,7 +191,7 @@ func (attr *Attributes) DelAttribute(key GnoAttribute) { func (attr *Attributes) GetAttributeKeys() []GnoAttribute { res := make([]GnoAttribute, 0, len(attr.data)) - for key, _ := range attr.data { + for key := range attr.data { res = append(res, key) } return res diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a52fdf01ab7..13455ac0d68 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -454,7 +454,7 @@ var preprocessing atomic.Int32 // - Assigns BlockValuePath to NameExprs. // - TODO document what it does. func Preprocess(store Store, ctx BlockNode, n Node) Node { - var clearSkip = false + clearSkip := false // First init static blocks of blocknodes. // This may have already happened. // Keep this function idemponent. @@ -4997,13 +4997,13 @@ func setNodeLines(nn Node) { Transcribe(nn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { switch stage { case TRANS_ENTER: - var nspan = n.GetSpan() + nspan := n.GetSpan() if nspan.IsZero() { if len(ns) == 0 { // Handled by TRANS_LEAVE. Case A. return n, TRANS_CONTINUE } - var lastSpan = ns[len(ns)-1].GetSpan() + lastSpan := ns[len(ns)-1].GetSpan() if lastSpan.IsZero() { // Handled by TRANS_LEAVE too. Case B. return n, TRANS_CONTINUE @@ -5022,7 +5022,7 @@ func setNodeLines(nn Node) { case TRANS_LEAVE: // TODO: Validate that all spans of elements are // strictly contained. - var nspan = n.GetSpan() + nspan := n.GetSpan() if nspan.IsZero() { // Case A: len(ns) == 0 // Case b: len(ns) > 0. diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index c183f6d4829..389ff06def6 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -51,14 +51,15 @@ const ( // // XXX move to pkg/gnolang/gotypecheck.go? func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( - gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error) { + gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, +) { gofset = token.NewFileSet() // This map is used to allow for function re-definitions, which are // allowed in Gno (testing context) but not in Go. This map links // each function identifier with a closure to remove its associated // declaration. - var delFunc = make(map[string]func()) + delFunc := make(map[string]func()) // Go parse and collect files from mpkg. for _, file := range mpkg.Files { @@ -87,7 +88,7 @@ func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var gof, err = parser.ParseFile( + gof, err := parser.ParseFile( gofset, path.Join(mpkg.Path, file.Name), file.Body, parseOpts) @@ -313,8 +314,8 @@ func addXform1(n Node, p string, f string, s Span, x xtype) { func addXform2IfMatched( xforms1 map[string]struct{}, xforms2 map[ast.Node]string, - gon ast.Node, p string, f string, s Span, x xtype) { - + gon ast.Node, p string, f string, s Span, x xtype, +) { xform1 := fmt.Sprintf("%s/%s:%v+%s", p, f, s, x) if _, exists := xforms1[xform1]; exists { if prior, exists := xforms2[gon]; exists { @@ -335,7 +336,6 @@ func addXform2IfMatched( // - dir: where to write to. // - xforms1: result of FindGno0p9Xforms(). func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct{}) error { - // Return if gno.mod is current. var mod *gnomod.File var err error @@ -359,7 +359,7 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution - var gof, err = parser.ParseFile( + gof, err := parser.ParseFile( gofset, path.Join(mpkg.Path, mfile.Name), mfile.Body, @@ -461,7 +461,7 @@ func checkXforms(xforms1 map[string]struct{}, xforms2 map[ast.Node]string, fname mismatch := false found := 0 XFORMS1_LOOP: - for xform1, _ := range xforms1 { + for xform1 := range xforms1 { if !strings.Contains(xform1, "/"+fname) { continue } @@ -476,7 +476,7 @@ XFORMS1_LOOP: mismatch = true } if mismatch { - for xform1, _ := range xforms1 { + for xform1 := range xforms1 { fmt.Println("xform1:", xform1) } for n2, xform2 := range xforms2 { @@ -492,17 +492,16 @@ XFORMS1_LOOP: // The main Go AST transpiling logic to make Gno code Gno 0.9. func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof *ast.File, xforms2 map[ast.Node]string) (err error) { - - var lastLine = 0 - var didRemoveCrossing = false - var setLast = func(end token.Pos) { + lastLine := 0 + didRemoveCrossing := false + setLast := func(end token.Pos) { posn := fs.Position(end) lastLine = posn.Line } - var getLine = func(pos token.Pos) int { + getLine := func(pos token.Pos) int { return fs.Position(pos).Line } - var inXforms2 = func(gon ast.Node, x xtype) bool { + inXforms2 := func(gon ast.Node, x xtype) bool { if xforms2 == nil { return false } @@ -514,7 +513,6 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof } astutil.Apply(gof, func(c *astutil.Cursor) bool { - // Handle newlines after crossing if didRemoveCrossing { gon := c.Node() @@ -557,7 +555,7 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof } case *ast.FuncLit: if inXforms2(gon, XTYPE_ADD_CURFUNC) { - gon.Type.Params.List = append([]*ast.Field{&ast.Field{ + gon.Type.Params.List = append([]*ast.Field{{ Names: []*ast.Ident{ast.NewIdent("cur")}, Type: ast.NewIdent("realm_XXX_TRANSPILE"), }}, gon.Type.Params.List...) @@ -565,7 +563,7 @@ func transpileGno0p9_part2(pkgPath string, fs *token.FileSet, fname string, gof } case *ast.FuncDecl: if inXforms2(gon, XTYPE_ADD_CURFUNC) { - gon.Type.Params.List = append([]*ast.Field{&ast.Field{ + gon.Type.Params.List = append([]*ast.Field{{ Names: []*ast.Ident{ast.NewIdent("cur")}, Type: ast.NewIdent("realm_XXX_TRANSPILE"), }}, gon.Type.Params.List...) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 2f8b44ba643..5e5f209b53d 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -778,7 +778,7 @@ func (x *BinaryExpr) checkCompatibility(n Node, xt, dt Type, checker func(t Type } // display xt as "untyped nil" if nil as Go does. - var untypedNil = func(t Type) string { + untypedNil := func(t Type) string { if t == nil { return "untyped nil" } else { diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 7202b59efa8..c88161546af 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -62,9 +62,10 @@ func StoreWithOptions( // process the mempackage after gno.MustReadMemPackage(). // * m.PreprocessFiles() if opts.PreprocessOnly. // * m.RunMemPackage() otherwise. - var _processMemPackage = func( + _processMemPackage := func( m *gno.Machine, mpkg *std.MemPackage, save bool) ( - pn *gno.PackageNode, pv *gno.PackageValue) { + pn *gno.PackageNode, pv *gno.PackageValue, + ) { if opts.PreprocessOnly { // Check the gno.mod gno version. mod, err := gno.ParseCheckGnoMod(mpkg) @@ -102,7 +103,7 @@ func StoreWithOptions( //---------------------------------------- // Main entrypoint for new test imports. - var getPackage = func(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { + getPackage := func(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { if pkgPath == "" { panic(fmt.Sprintf("invalid zero package path in testStore().pkgGetter")) } From 086ff7ee7dc0ddeaa623298be4d5ff9bb0f4b298 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 16 May 2025 12:04:41 -0700 Subject: [PATCH 31/83] ... --- gnovm/cmd/gno/test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index f62422d05ba..3577a3bc525 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -254,7 +254,7 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { } else if cmd.verbose { io.ErrPrintfln("%s: module is draft, skipping type check", pkgPath) } - errs = test.Test(mpkg, pkg.Dir, opts) + errs := test.Test(mpkg, pkg.Dir, opts) if errs != nil { didError = true io.ErrPrintln(errs) From a27e8edf695f17f4b293e79f0a69073de4f6df1c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 17 May 2025 06:38:56 -0700 Subject: [PATCH 32/83] fix stdlibs/fmt test --- gnovm/pkg/gnolang/machine.go | 3 ++- gnovm/pkg/gnolang/preprocess.go | 32 ++++++++++++++++++---------- gnovm/pkg/gnolang/type_check.go | 4 ++-- gnovm/pkg/gnolang/type_check_test.go | 20 ++++++++--------- gnovm/tests/stdlibs/fmt/fmt_test.gno | 2 +- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 3ebf7c23530..19e52a16454 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -816,7 +816,8 @@ func (m *Machine) EvalStaticTypeOf(last BlockNode, x Expr) Type { } // X must have been preprocessed or a predefined func lit expr. if x.GetAttribute(ATTR_PREPROCESSED) == nil && - x.GetAttribute(ATTR_PREPROCESS_SKIPPED) == nil { + x.GetAttribute(ATTR_PREPROCESS_SKIPPED) == nil && + x.GetAttribute(ATTR_PREPROCESS_INCOMPLETE) == nil { panic(fmt.Sprintf( "Machine.EvalStaticTypeOf(x) expression not yet preprocessed: %s", x.String())) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 13455ac0d68..cdba832fa3f 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -731,8 +731,15 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // Machine still needs it. Clear it @ initStaticBlocks. // n.DelAttribute(ATTR_PREPROCESS_SKIPPED) for _, p := range ns { + // Prevent parents from being marked as attr + // preprocessed. Be not concerned about any inner + // Preprocess() calls for newly constructed nodes: + // either this node will be inside it, in which case it + // too will be marked incomplete, or, it won't be + // inside it, in which case it will complete. p.SetAttribute(ATTR_PREPROCESS_INCOMPLETE, true) } + // n.SetAttribute(ATTR_PREPROCESS_INCOMPLETE, true) return n, TRANS_SKIP } // push func body block. @@ -977,9 +984,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { case TRANS_LEAVE: // mark as preprocessed so that it can be used // in evalStaticType(store,). - if n.GetAttribute(ATTR_PREPROCESS_INCOMPLETE) == nil { - n.SetAttribute(ATTR_PREPROCESSED, true) - } + setPreprocessed(n) // Defer pop block from stack. // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK @@ -1605,7 +1610,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // for (*a)[low : high : max] dt = dt.Elem() n.X = &StarExpr{X: n.X} - n.X.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(n.X) } switch dt.Kind() { case StringKind, ArrayKind, SliceKind: @@ -1811,7 +1816,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // // convert to (&x).m, but leave xt as is. n.X = &RefExpr{X: n.X} - n.X.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(n.X) switch tr[len(tr)-1].Type { case VPDerefPtrMethod: // When ptr method was called like x.y.z(), where x @@ -1837,7 +1842,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // is not pointer type, replace n.X with // &RefExpr{X: n.X}. n.X = &RefExpr{X: n.X} - n.X.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(n.X) } // bound method or underlying. // TODO check for unexported fields. @@ -3424,7 +3429,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { } } // cx.SetSpan(x.GetSpan()) - cx.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(cx) setConstAttrs(cx) return cx } @@ -3433,7 +3438,7 @@ func constType(source Expr, t Type) *constTypeExpr { cx := &constTypeExpr{Source: source} cx.Type = t // cx.SetSpan(source.GetSpan()) - cx.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(cx) return cx } @@ -3448,6 +3453,12 @@ func setConstAttrs(cx *ConstExpr) { } } +func setPreprocessed(x Expr) { + if x.GetAttribute(ATTR_PREPROCESS_INCOMPLETE) == nil { + x.SetAttribute(ATTR_PREPROCESSED, true) + } +} + func packageOf(last BlockNode) *PackageNode { for { if pn, ok := last.(*PackageNode); ok { @@ -4000,7 +4011,6 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin ct.String())) } case *FuncLitExpr: - // XXX why would astype && be necessary? un, directR = findUndefinedT(store, last, &cx.Type, stack, defining, isalias, astype && isalias) if un != "" { return @@ -4612,7 +4622,7 @@ func constInt(source Expr, i int64) *ConstExpr { cx := &ConstExpr{Source: source} cx.T = IntType cx.SetInt(i) - cx.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(cx) return cx } @@ -4620,7 +4630,7 @@ func constUntypedBigint(source Expr, i64 int64) *ConstExpr { cx := &ConstExpr{Source: source} cx.T = UntypedBigintType cx.V = BigintValue{big.NewInt(i64)} - cx.SetAttribute(ATTR_PREPROCESSED, true) + setPreprocessed(cx) return cx } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 5e5f209b53d..e8cd0d9379e 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -177,7 +177,7 @@ func assertComparable2(dt Type) { } } -func maybeNil(t Type) bool { +func mayBeNil(t Type) bool { switch baseOf(t).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType, *ChanType: // we don't have unsafePointer return true @@ -414,7 +414,7 @@ func checkAssignableTo(n Node, xt, dt Type, autoNative bool) (err error) { if dt == nil || dt.Kind() == InterfaceKind { return nil } - if !maybeNil(dt) { + if !mayBeNil(dt) { switch n := n.(type) { case *ValueDecl: return errors.New("cannot use nil as %v value in variable declaration", dt) diff --git a/gnovm/pkg/gnolang/type_check_test.go b/gnovm/pkg/gnolang/type_check_test.go index 7fddf2c65d0..dbb4f543a75 100644 --- a/gnovm/pkg/gnolang/type_check_test.go +++ b/gnovm/pkg/gnolang/type_check_test.go @@ -10,7 +10,7 @@ func TestCheckAssignableTo(t *testing.T) { xt Type dt Type autoNative bool - wantPanic bool + wantError string }{ { name: "nil to nil", @@ -30,8 +30,8 @@ func TestCheckAssignableTo(t *testing.T) { { name: "nil to non-nillable", xt: nil, - dt: PrimitiveType(StringKind), - wantPanic: true, + dt: StringType, + wantError: "cannot use nil as string value", }, { name: "interface to interface", @@ -44,14 +44,14 @@ func TestCheckAssignableTo(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - if tt.wantPanic { - defer func() { - if r := recover(); r == nil { - t.Errorf("checkAssignableTo() did not panic, want panic") - } - }() + err := checkAssignableTo(nil, tt.xt, tt.dt, tt.autoNative) + if tt.wantError != "" { + if err.Error() != tt.wantError { + t.Errorf("checkAssignableTo() returned wrong error: want: %v got: %v", tt.wantError, err.Error()) + } + } else if err != nil { + t.Errorf("checkAssignableTo() returned unexpected wrong error: got: %v", err.Error()) } - checkAssignableTo(nil, tt.xt, tt.dt, tt.autoNative) }) } } diff --git a/gnovm/tests/stdlibs/fmt/fmt_test.gno b/gnovm/tests/stdlibs/fmt/fmt_test.gno index 7a60ae3a458..bcfcf8bb882 100644 --- a/gnovm/tests/stdlibs/fmt/fmt_test.gno +++ b/gnovm/tests/stdlibs/fmt/fmt_test.gno @@ -628,7 +628,7 @@ var fmtTests = []struct { // go syntax {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, {"%#v", new(byte), "(*uint8)(0xPTR)"}, - {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, + {"%#v", TestFmtInterface, "(func(*testing/base.T))(0xPTR)"}, {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, {"%#v", 1000000000, "1000000000"}, {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`}, From 495f2c313f777ad39ad9c91fdd2645bd9f7d6555 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 17 May 2025 19:09:51 -0700 Subject: [PATCH 33/83] fix stdlib tests except one re: genstd --- gnovm/cmd/gno/common.go | 189 +++++++++++++++++ gnovm/cmd/gno/tool_lint.go | 195 +----------------- gnovm/pkg/gnolang/gotypecheck.go | 75 +++++-- gnovm/stdlibs/encoding/csv/writer_test.gno | 11 +- gnovm/stdlibs/math/overflow/overflow_test.gno | 2 +- gnovm/stdlibs/std/crypto_test.gno | 2 +- gnovm/stdlibs/std/emit_event_test.go | 2 +- gnovm/stdlibs/std/native_test.go | 2 +- gnovm/stdlibs/std/params_test.go | 2 +- gnovm/stdlibs/strings/builder_test.gno | 2 +- gnovm/stdlibs/strings/printtrie_test.gno | 2 +- gnovm/stdlibs/strings/reader_test.gno | 2 +- gnovm/stdlibs/strings/replace_test.gno | 2 +- 13 files changed, 274 insertions(+), 214 deletions(-) create mode 100644 gnovm/cmd/gno/common.go diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go new file mode 100644 index 00000000000..8e25210f82e --- /dev/null +++ b/gnovm/cmd/gno/common.go @@ -0,0 +1,189 @@ +package main + +import ( + "fmt" + "go/scanner" + "io" + "os" + "path/filepath" + "regexp" + "strings" + + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/multierr" +) + +type gnoCode string + +const ( + gnoUnknownError gnoCode = "gnoUnknownError" + gnoReadError = "gnoReadError" + gnoImportError = "gnoImportError" + gnoGnoModError = "gnoGnoModError" + gnoPreprocessError = "gnoPreprocessError" + gnoParserError = "gnoParserError" + gnoTypeCheckError = "gnoTypeCheckError" + + // TODO: add new gno codes here. +) + +type gnoIssue struct { + Code gnoCode + Msg string + Confidence float64 // 1 is 100% + Location string // file:line, or equivalent + // TODO: consider writing fix suggestions +} + +func (i gnoIssue) String() string { + // TODO: consider crafting a doc URL based on Code. + return fmt.Sprintf("%s: %s (code=%s)", i.Location, i.Msg, i.Code) +} + +// Gno parses and sorts mpkg files into the following filesets: +// - fset: all normal and _test.go files in package excluding `package xxx_test` +// integration *_test.gno files. +// - _tests: `package xxx_test` integration *_test.gno files, each in their +// own file set. +// - ftests: *_filetest.gno file tests, each in their own file set. +func sourceAndTestFileset(mpkg *std.MemPackage) ( + all, fset *gno.FileSet, _tests, ftests []*gno.FileSet, +) { + all = &gno.FileSet{} + fset = &gno.FileSet{} + for _, mfile := range mpkg.Files { + if !strings.HasSuffix(mfile.Name, ".gno") { + continue // Skip non-GNO files + } + + n := gno.MustParseFile(mfile.Name, mfile.Body) + if n == nil { + continue // Skip empty files + } + all.AddFiles(n) + if string(n.PkgName) == string(mpkg.Name)+"_test" { + // A xxx_file integration test is a package of its own. + fset := &gno.FileSet{} + fset.AddFiles(n) + _tests = append(_tests, fset) + } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { + // A _filetest.gno is a package of its own. + fset := &gno.FileSet{} + fset.AddFiles(n) + ftests = append(ftests, fset) + } else { + // All normal package files and, + // _test.gno files that aren't xxx_test. + fset.AddFiles(n) + } + } + return +} + +func guessSourcePath(pkgPath, fname string) string { + if info, err := os.Stat(pkgPath); !os.IsNotExist(err) && !info.IsDir() { + pkgPath = filepath.Dir(pkgPath) + } + + fnameJoin := filepath.Join(pkgPath, fname) + if _, err := os.Stat(fnameJoin); !os.IsNotExist(err) { + return filepath.Clean(fnameJoin) + } + + if _, err := os.Stat(fname); !os.IsNotExist(err) { + return filepath.Clean(fname) + } + + return filepath.Clean(pkgPath) +} + +// reParseRecover is a regex designed to parse error details from a string. +// It extracts the file location, line number, and error message from a +// formatted error string. +// XXX: Ideally, error handling should encapsulate location details within a +// dedicated error type. +var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) + +func printError(w io.WriteCloser, dir, pkgPath string, err error) { + switch err := err.(type) { + case *gno.PreprocessError: + err2 := err.Unwrap() + fmt.Fprintln(w, issueFromError( + dir, pkgPath, err2, gnoPreprocessError).String()) + case gno.ImportError: + fmt.Fprintln(w, issueFromError( + dir, pkgPath, err, gnoImportError).String()) + case scanner.ErrorList: + for _, err := range err { + fmt.Fprintln(w, issueFromError( + dir, + pkgPath, + err, + gnoParserError, + ).String()) + } + default: // error type + errors := multierr.Errors(err) + if len(errors) == 1 { + fmt.Fprintln(w, issueFromError( + dir, + pkgPath, + err, + gnoUnknownError, + ).String()) + return + } + for _, err := range errors { + printError(w, dir, pkgPath, err) + } + } +} + +func catchPanic(dir, pkgPath string, stderr io.WriteCloser, action func()) (didPanic bool) { + defer func() { + // Errors catched here mostly come from: + // gnovm/pkg/gnolang/preprocess.go + r := recover() + if r == nil { + return + } + didPanic = true + if err, ok := r.(error); ok { + printError(stderr, dir, pkgPath, err) + } else { + panic(r) + } + }() + + action() + return +} + +func issueFromError(dir, pkgPath string, err error, code gnoCode) gnoIssue { + var issue gnoIssue + issue.Confidence = 1 + issue.Code = code + + parsedError := strings.TrimSpace(err.Error()) + parsedError = replaceWithDirPath(parsedError, pkgPath, dir) + parsedError = strings.TrimPrefix(parsedError, pkgPath+"/") + + matches := reParseRecover.FindStringSubmatch(parsedError) + if len(matches) > 0 { + sourcepath := guessSourcePath(pkgPath, matches[1]) + issue.Location = sourcepath + matches[2] + issue.Msg = strings.TrimSpace(matches[3]) + } else { + issue.Location = fmt.Sprintf("%s:0", filepath.Clean(pkgPath)) + issue.Msg = err.Error() + } + return issue +} + +func replaceWithDirPath(s, pkgPath, dir string) string { + if strings.HasPrefix(s, pkgPath) { + return filepath.Clean(dir + s[len(pkgPath):]) + } + return s +} diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 982c917ff72..b72f7281ca3 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -14,8 +14,6 @@ import ( "os" "path" "path/filepath" - "regexp" - "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -71,33 +69,6 @@ func (c *lintCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar(&c.autoGnomod, "auto-gnomod", true, "auto-generate gno.mod file if not already present.") } -type lintCode string - -const ( - lintUnknownError lintCode = "lintUnknownError" - lintReadError = "lintReadError" - lintImportError = "lintImportError" // XXX break this out - lintGnoModError = "lintGnoModError" - lintPreprocessError = "lintPreprocessError" - lintParserError = "lintParserError" - lintTypeCheckError = "lintTypeCheckError" - - // TODO: add new linter codes here. -) - -type lintIssue struct { - Code lintCode - Msg string - Confidence float64 // 1 is 100% - Location string // file:line, or equivalent - // TODO: consider writing fix suggestions -} - -func (i lintIssue) String() string { - // TODO: consider crafting a doc URL based on Code. - return fmt.Sprintf("%s: %s (code=%s)", i.Location, i.Msg, i.Code) -} - func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Show a help message by default. if len(args) == 0 { @@ -163,8 +134,8 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } } if err != nil { - issue := lintIssue{ - Code: lintGnoModError, + issue := gnoIssue{ + Code: gnoGnoModError, Confidence: 1, // ?? Location: fpath, Msg: err.Error(), @@ -181,7 +152,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { io.ErrPrintln(issueFromError( - dir, pkgPath, err, lintReadError).String()) + dir, pkgPath, err, gnoReadError).String()) hasError = true continue } @@ -189,7 +160,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Perform imports using the parent store. if err := test.LoadImports(ts, mpkg); err != nil { io.ErrPrintln(issueFromError( - dir, pkgPath, err, lintImportError).String()) + dir, pkgPath, err, gnoImportError).String()) hasError = true continue } @@ -284,7 +255,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { return nil } -// Wrapper around TypeCheckMemPackage() to io.ErrPrintln(lintIssue{}). +// Wrapper around TypeCheckMemPackage() to io.ErrPrintln(gnoIssue{}). // Prints and returns errors. Panics upon an unexpected error. func lintTypeCheck( // Args: @@ -311,8 +282,8 @@ func lintTypeCheck( case types.Error: loc := err.Fset.Position(err.Pos).String() loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(lintIssue{ - Code: lintTypeCheckError, + io.ErrPrintln(gnoIssue{ + Code: gnoTypeCheckError, Msg: err.Msg, Confidence: 1, Location: loc, @@ -321,8 +292,8 @@ func lintTypeCheck( for _, scErr := range err { loc := scErr.Pos.String() loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(lintIssue{ - Code: lintParserError, + io.ErrPrintln(gnoIssue{ + Code: gnoParserError, Msg: scErr.Msg, Confidence: 1, Location: loc, @@ -331,8 +302,8 @@ func lintTypeCheck( case scanner.Error: loc := err.Pos.String() loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(lintIssue{ - Code: lintParserError, + io.ErrPrintln(gnoIssue{ + Code: gnoParserError, Msg: err.Msg, Confidence: 1, Location: loc, @@ -345,147 +316,3 @@ func lintTypeCheck( lerr = tcErrs return } - -// Gno parses and sorts mpkg files into the following filesets: -// - fset: all normal and _test.go files in package excluding `package xxx_test` -// integration *_test.gno files. -// - _tests: `package xxx_test` integration *_test.gno files, each in their -// own file set. -// - ftests: *_filetest.gno file tests, each in their own file set. -func sourceAndTestFileset(mpkg *std.MemPackage) ( - all, fset *gno.FileSet, _tests, ftests []*gno.FileSet, -) { - all = &gno.FileSet{} - fset = &gno.FileSet{} - for _, mfile := range mpkg.Files { - if !strings.HasSuffix(mfile.Name, ".gno") { - continue // Skip non-GNO files - } - - n := gno.MustParseFile(mfile.Name, mfile.Body) - if n == nil { - continue // Skip empty files - } - all.AddFiles(n) - if string(n.PkgName) == string(mpkg.Name)+"_test" { - // A xxx_file integration test is a package of its own. - fset := &gno.FileSet{} - fset.AddFiles(n) - _tests = append(_tests, fset) - } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { - // A _filetest.gno is a package of its own. - fset := &gno.FileSet{} - fset.AddFiles(n) - ftests = append(ftests, fset) - } else { - // All normal package files and, - // _test.gno files that aren't xxx_test. - fset.AddFiles(n) - } - } - return -} - -func guessSourcePath(pkgPath, fname string) string { - if info, err := os.Stat(pkgPath); !os.IsNotExist(err) && !info.IsDir() { - pkgPath = filepath.Dir(pkgPath) - } - - fnameJoin := filepath.Join(pkgPath, fname) - if _, err := os.Stat(fnameJoin); !os.IsNotExist(err) { - return filepath.Clean(fnameJoin) - } - - if _, err := os.Stat(fname); !os.IsNotExist(err) { - return filepath.Clean(fname) - } - - return filepath.Clean(pkgPath) -} - -// reParseRecover is a regex designed to parse error details from a string. -// It extracts the file location, line number, and error message from a -// formatted error string. -// XXX: Ideally, error handling should encapsulate location details within a -// dedicated error type. -var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) - -func catchPanic(dir, pkgPath string, stderr goio.WriteCloser, action func()) (didPanic bool) { - defer func() { - // Errors catched here mostly come from: - // gnovm/pkg/gnolang/preprocess.go - r := recover() - if r == nil { - return - } - didPanic = true - switch verr := r.(type) { - case *gno.PreprocessError: - err := verr.Unwrap() - fmt.Fprintln(stderr, issueFromError( - dir, pkgPath, err, lintPreprocessError).String()) - case error: - errors := multierr.Errors(verr) - for _, err := range errors { - errList, ok := err.(scanner.ErrorList) - if ok { - for _, errorInList := range errList { - fmt.Fprintln(stderr, issueFromError( - dir, - pkgPath, - errorInList, - lintParserError, - ).String()) - } - } else { - fmt.Fprintln(stderr, issueFromError( - dir, - pkgPath, - err, - lintUnknownError, - ).String()) - } - } - case string: - fmt.Fprintln(stderr, issueFromError( - dir, - pkgPath, - errors.New(verr), - lintUnknownError, - ).String()) - default: - panic(r) - } - }() - - action() - return -} - -func issueFromError(dir, pkgPath string, err error, code lintCode) lintIssue { - var issue lintIssue - issue.Confidence = 1 - issue.Code = code - - parsedError := strings.TrimSpace(err.Error()) - parsedError = replaceWithDirPath(parsedError, pkgPath, dir) - parsedError = strings.TrimPrefix(parsedError, pkgPath+"/") - - matches := reParseRecover.FindStringSubmatch(parsedError) - if len(matches) > 0 { - sourcepath := guessSourcePath(pkgPath, matches[1]) - issue.Location = sourcepath + matches[2] - issue.Msg = strings.TrimSpace(matches[3]) - } else { - issue.Location = fmt.Sprintf("%s:0", filepath.Clean(pkgPath)) - issue.Msg = err.Error() - } - return issue -} - -func replaceWithDirPath(s, pkgPath, dir string) string { - if strings.HasPrefix(s, pkgPath) { - return filepath.Clean(dir + s[len(pkgPath):]) - } - return s -} diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 56316760f34..0158e436244 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -36,7 +36,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( gimp = &gnoImporter{ pkgPath: mpkg.Path, getter: getter, - cache: map[string]gnoImporterResult{}, + cache: map[string]*gnoImporterResult{}, cfg: &types.Config{ Error: func(err error) { gimp.Error(err) @@ -53,8 +53,9 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( } type gnoImporterResult struct { - pkg *types.Package - err error + pkg *types.Package + err error + pending bool // for cyclic import detection } // gimp. @@ -65,9 +66,10 @@ type gnoImporter struct { // when importing self (from xxx_test package) include *_test.gno. pkgPath string getter MemPackageGetter - cache map[string]gnoImporterResult + cache map[string]*gnoImporterResult cfg *types.Config - errors error // multierr + errors error // multierr + stack []string // stack of pkgpaths for cyclic import detection } // Unused, but satisfies the Importer interface. @@ -80,21 +82,36 @@ func (gimp *gnoImporter) Error(err error) { gimp.errors = multierr.Append(gimp.errors, err) } -type importNotFoundError string - -func (e importNotFoundError) Error() string { return "import not found: " + string(e) } - // ImportFrom returns the imported package for the given import // pkgPath when imported by a package file located in dir. func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*types.Package, error) { - if pkg, ok := gimp.cache[pkgPath]; ok { - return pkg.pkg, pkg.err + if result, ok := gimp.cache[pkgPath]; ok { + if gimp.pkgPath == pkgPath { + // continue: xxx_test importing self. + } else if result.pending { + idx := slices.Index(gimp.stack, pkgPath) + loop := gimp.stack[idx:] + err := ImportCycleError(loop) + result.err = err + // NOTE: returning an error loses type info? + // return nil, ImportCycleError(loop) + panic(err) + } else if gimp.pkgPath == pkgPath { + // continue: xxx_test importing self. + } else { + return result.pkg, result.err + } } + gimp.cache[pkgPath] = &gnoImporterResult{pending: true} + gimp.stack = append(gimp.stack, pkgPath) + defer func() { gimp.stack = gimp.stack[:len(gimp.stack)-1] }() mpkg := gimp.getter.GetMemPackage(pkgPath) if mpkg == nil { - err := importNotFoundError(pkgPath) - gimp.cache[pkgPath] = gnoImporterResult{err: err} - return nil, err + err := ImportNotFoundError(pkgPath) + gimp.cache[pkgPath] = &gnoImporterResult{err: err} + // NOTE: returning an error loses type info? + // return nil, err + panic(err) } pmode := ParseModeProduction // don't parse test files for imports... if gimp.pkgPath == pkgPath { @@ -110,7 +127,7 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ // Panic instead to quit quickly. panic(errs) } - gimp.cache[pkgPath] = gnoImporterResult{pkg: pkg, err: errs} + gimp.cache[pkgPath] = &gnoImporterResult{pkg: pkg, err: errs, pending: false} return pkg, errs } @@ -232,3 +249,31 @@ func deleteOldIdents(idents map[string]func(), gof *ast.File) { } } } + +//---------------------------------------- +// Errors + +type ImportNotFoundError string + +func (e ImportNotFoundError) Error() string { + return "import not found: " + string(e) +} + +type ImportCycleError []string + +func (e ImportCycleError) Error() string { + return fmt.Sprintf("cyclic import detected: %s -> %s", strings.Join(e, " -> "), e[0]) +} + +type ImportError interface { + assertImportError() + error +} + +func (e ImportNotFoundError) assertImportError() {} +func (e ImportCycleError) assertImportError() {} + +var ( + _ ImportError = ImportNotFoundError("") + _ ImportError = ImportCycleError(nil) +) diff --git a/gnovm/stdlibs/encoding/csv/writer_test.gno b/gnovm/stdlibs/encoding/csv/writer_test.gno index 1407f3c670a..40d147b6a6c 100644 --- a/gnovm/stdlibs/encoding/csv/writer_test.gno +++ b/gnovm/stdlibs/encoding/csv/writer_test.gno @@ -6,7 +6,6 @@ package csv import ( "bytes" - "encoding/csv" "errors" "strings" "testing" @@ -21,7 +20,7 @@ func TestWriteCSV(t *testing.T) { } var buf bytes.Buffer - w := csv.NewWriter(&buf) + w := NewWriter(&buf) err := w.WriteAll(records) if err != nil { t.Errorf("Unexpected error: %v", err) @@ -74,7 +73,7 @@ var writeTests = []struct { func TestWrite(t *testing.T) { for n, tt := range writeTests { b := &strings.Builder{} - f := csv.NewWriter(b) + f := NewWriter(b) f.UseCRLF = tt.UseCRLF if tt.Comma != 0 { f.Comma = tt.Comma @@ -98,7 +97,7 @@ func (e errorWriter) Write(b []byte) (int, error) { func TestError(t *testing.T) { b := &bytes.Buffer{} - f := csv.NewWriter(b) + f := NewWriter(b) f.Write([]string{"abc"}) f.Flush() err := f.Error() @@ -106,7 +105,7 @@ func TestError(t *testing.T) { t.Errorf("Unexpected error: %s\n", err) } - f = csv.NewWriter(errorWriter{}) + f = NewWriter(errorWriter{}) f.Write([]string{"abc"}) f.Flush() err = f.Error() @@ -124,7 +123,7 @@ var benchmarkWriteData = [][]string{ func BenchmarkWrite(b *testing.B) { for i := 0; i < b.N; i++ { - w := csv.NewWriter(&bytes.Buffer{}) + w := NewWriter(&bytes.Buffer{}) err := w.WriteAll(benchmarkWriteData) if err != nil { b.Fatal(err) diff --git a/gnovm/stdlibs/math/overflow/overflow_test.gno b/gnovm/stdlibs/math/overflow/overflow_test.gno index b7881aec480..72898307b3b 100644 --- a/gnovm/stdlibs/math/overflow/overflow_test.gno +++ b/gnovm/stdlibs/math/overflow/overflow_test.gno @@ -2,7 +2,7 @@ package overflow import ( "math" - "testing" + testing "testing/base" ) // sample all possibilities of 8 bit numbers diff --git a/gnovm/stdlibs/std/crypto_test.gno b/gnovm/stdlibs/std/crypto_test.gno index 70b42e43860..65c8242a74b 100644 --- a/gnovm/stdlibs/std/crypto_test.gno +++ b/gnovm/stdlibs/std/crypto_test.gno @@ -1,7 +1,7 @@ package std import ( - "testing" + testing "testing/base" ) func TestValid(t *testing.T) { diff --git a/gnovm/stdlibs/std/emit_event_test.go b/gnovm/stdlibs/std/emit_event_test.go index 7b4c8ae9d0e..2bf25539b9d 100644 --- a/gnovm/stdlibs/std/emit_event_test.go +++ b/gnovm/stdlibs/std/emit_event_test.go @@ -2,7 +2,7 @@ package std import ( "encoding/json" - "testing" + testing "testing/base" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/sdk" diff --git a/gnovm/stdlibs/std/native_test.go b/gnovm/stdlibs/std/native_test.go index 23f3d244aab..cd89e7aab1b 100644 --- a/gnovm/stdlibs/std/native_test.go +++ b/gnovm/stdlibs/std/native_test.go @@ -2,7 +2,7 @@ package std import ( "fmt" - "testing" + testing "testing/base" "github.com/stretchr/testify/assert" diff --git a/gnovm/stdlibs/std/params_test.go b/gnovm/stdlibs/std/params_test.go index 21de716e69b..73f70af49c1 100644 --- a/gnovm/stdlibs/std/params_test.go +++ b/gnovm/stdlibs/std/params_test.go @@ -1,7 +1,7 @@ package std import ( - "testing" + testing "testing/base" ) // XXX move elsewhere in the gno.land/ dir. diff --git a/gnovm/stdlibs/strings/builder_test.gno b/gnovm/stdlibs/strings/builder_test.gno index 1bbff0249ad..ec0283349d5 100644 --- a/gnovm/stdlibs/strings/builder_test.gno +++ b/gnovm/stdlibs/strings/builder_test.gno @@ -7,7 +7,7 @@ package strings_test import ( "bytes" "strings" - "testing" + testing "testing/base" "unicode/utf8" ) diff --git a/gnovm/stdlibs/strings/printtrie_test.gno b/gnovm/stdlibs/strings/printtrie_test.gno index a51208f4756..7057498bbe6 100644 --- a/gnovm/stdlibs/strings/printtrie_test.gno +++ b/gnovm/stdlibs/strings/printtrie_test.gno @@ -2,7 +2,7 @@ package strings_test import ( "strings" - "testing" + testing "testing/base" ) func TestGenericTrieBuilding(t *testing.T) { diff --git a/gnovm/stdlibs/strings/reader_test.gno b/gnovm/stdlibs/strings/reader_test.gno index a8047311550..2363023f190 100644 --- a/gnovm/stdlibs/strings/reader_test.gno +++ b/gnovm/stdlibs/strings/reader_test.gno @@ -7,7 +7,7 @@ package strings_test import ( "io" "strings" - "testing" + testing "testing/base" ) func TestReader(t *testing.T) { diff --git a/gnovm/stdlibs/strings/replace_test.gno b/gnovm/stdlibs/strings/replace_test.gno index dc4858dcc5c..52e92c60255 100644 --- a/gnovm/stdlibs/strings/replace_test.gno +++ b/gnovm/stdlibs/strings/replace_test.gno @@ -8,7 +8,7 @@ import ( "bytes" "fmt" "strings" - "testing" + testing "testing/base" ) var htmlEscaper = strings.NewReplacer( From 8b2b7f247c6c0b9d31c33ff28a79d8bbf30b11fa Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 17 May 2025 21:13:26 -0700 Subject: [PATCH 34/83] lint.*Error -> gno.*Error --- gnovm/cmd/gno/run_test.go | 8 ++++---- gnovm/cmd/gno/testdata/lint/bad_import.txtar | 2 +- gnovm/cmd/gno/testdata/lint/file_error.txtar | 4 ++-- .../cmd/gno/testdata/lint/not_declared.txtar | 2 +- .../gno/testdata/test/unknown_package.txtar | 4 ++-- gnovm/cmd/gno/tool_lint_test.go | 20 +++++++++---------- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index 70d16de04d9..5ef7cc66807 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -90,10 +90,10 @@ func TestRunApp(t *testing.T) { args: []string{"run", "../../tests/integ/several-files-multiple-errors/"}, stderrShouldContain: func() string { lines := []string{ - "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=gnoParserError)", } return strings.Join(lines, "\n") + "\n" }(), diff --git a/gnovm/cmd/gno/testdata/lint/bad_import.txtar b/gnovm/cmd/gno/testdata/lint/bad_import.txtar index e58fcb3cc6a..944891da1ce 100644 --- a/gnovm/cmd/gno/testdata/lint/bad_import.txtar +++ b/gnovm/cmd/gno/testdata/lint/bad_import.txtar @@ -19,4 +19,4 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -bad_file.gno:3:8: unknown import path python (code=lintImportError) +bad_file.gno:3:8: unknown import path python (code=gnoImportError) diff --git a/gnovm/cmd/gno/testdata/lint/file_error.txtar b/gnovm/cmd/gno/testdata/lint/file_error.txtar index efb5054017b..0ab3b6897c6 100644 --- a/gnovm/cmd/gno/testdata/lint/file_error.txtar +++ b/gnovm/cmd/gno/testdata/lint/file_error.txtar @@ -20,5 +20,5 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -i_have_error_test.gno:6:7: undefined: undefined_variable (code=lintTypeCheckError) -i_have_error_test.gno:6:2: declared and not used: i (code=lintTypeCheckError) +i_have_error_test.gno:6:7: undefined: undefined_variable (code=gnoTypeCheckError) +i_have_error_test.gno:6:2: declared and not used: i (code=gnoTypeCheckError) diff --git a/gnovm/cmd/gno/testdata/lint/not_declared.txtar b/gnovm/cmd/gno/testdata/lint/not_declared.txtar index 84778f6a1fb..90682638b26 100644 --- a/gnovm/cmd/gno/testdata/lint/not_declared.txtar +++ b/gnovm/cmd/gno/testdata/lint/not_declared.txtar @@ -18,4 +18,4 @@ module gno.land/p/demo/hello -- stdout.golden -- -- stderr.golden -- -bad_file.gno:4:2: undefined: hello (code=lintTypeCheckError) +bad_file.gno:4:2: undefined: hello (code=gnoTypeCheckError) diff --git a/gnovm/cmd/gno/testdata/test/unknown_package.txtar b/gnovm/cmd/gno/testdata/test/unknown_package.txtar index aa0f18c169f..bc603bc418b 100644 --- a/gnovm/cmd/gno/testdata/test/unknown_package.txtar +++ b/gnovm/cmd/gno/testdata/test/unknown_package.txtar @@ -3,8 +3,8 @@ ! gno test -v . ! stdout .+ -# XXX catch and convert to lintImportError -stderr 'contract.gno:3:8: could not import foobarbaz \(import not found: foobarbaz\) \(code=lintUnknownError\)' +# XXX catch and convert to gnoImportError +stderr 'contract.gno:3:8: could not import foobarbaz \(import not found: foobarbaz\) \(code=gnoUnknownError\)' -- contract.gno -- package contract diff --git a/gnovm/cmd/gno/tool_lint_test.go b/gnovm/cmd/gno/tool_lint_test.go index be7c8187082..7a45e8cdb1c 100644 --- a/gnovm/cmd/gno/tool_lint_test.go +++ b/gnovm/cmd/gno/tool_lint_test.go @@ -13,32 +13,32 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "../../tests/integ/run_main/", "-auto-gnomod=false"}, - stderrShouldContain: "../../tests/integ/run_main/gno.mod: could not read gno.mod file: stat ../../tests/integ/run_main/gno.mod: no such file or directory (code=lintGnoModError)", + stderrShouldContain: "../../tests/integ/run_main/gno.mod: could not read gno.mod file: stat ../../tests/integ/run_main/gno.mod: no such file or directory (code=gnoGnoModError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/undefined_variable_test/undefined_variables_test.gno"}, - stderrShouldContain: "../../tests/integ/undefined_variable_test/undefined_variables_test.gno:6:28: undefined: toto (code=lintTypeCheckError)", + stderrShouldContain: "../../tests/integ/undefined_variable_test/undefined_variables_test.gno:6:28: undefined: toto (code=gnoTypeCheckError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/package_not_declared/main.gno"}, - stderrShouldContain: "../../tests/integ/package_not_declared/main.gno:4:2: undefined: fmt (code=lintTypeCheckError)", + stderrShouldContain: "../../tests/integ/package_not_declared/main.gno:4:2: undefined: fmt (code=gnoTypeCheckError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/several-lint-errors/main.gno"}, - stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5:5: expected ';', found example (code=lintParserError)\n../../tests/integ/several-lint-errors/main.gno:6", + stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5:5: expected ';', found example (code=gnoParserError)\n../../tests/integ/several-lint-errors/main.gno:6", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/several-files-multiple-errors/main.gno"}, stderrShouldContain: func() string { lines := []string{ - "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=lintParserError)", - "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=lintParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:3:5: expected 'IDENT', found '{' (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/file2.gno:5:1: expected type, found '}' (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:5:5: expected ';', found example (code=gnoParserError)", + "../../tests/integ/several-files-multiple-errors/main.gno:6:2: expected '}', found 'EOF' (code=gnoParserError)", } return strings.Join(lines, "\n") + "\n" }(), @@ -54,12 +54,12 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "../../tests/integ/invalid_gno_file/"}, - stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=lintReadError)", + stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=gnoReadError)", errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/typecheck_missing_return/"}, - stderrShouldContain: "../../tests/integ/typecheck_missing_return/main.gno:5:1: missing return (code=lintTypeCheckError)", + stderrShouldContain: "../../tests/integ/typecheck_missing_return/main.gno:5:1: missing return (code=gnoTypeCheckError)", errShouldBe: "exit code: 1", }, { From 33454fb1cea88a1b16fc49343dc1d3756fdfd56f Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 18 May 2025 16:08:36 -0700 Subject: [PATCH 35/83] fix all gnovm tests; FINALLY --- gnovm/cmd/gno/common.go | 74 +++++++--- gnovm/cmd/gno/test.go | 3 +- gnovm/cmd/gno/testdata/lint/bad_import.txtar | 2 +- .../gno/testdata/test/unknown_package.txtar | 2 +- gnovm/cmd/gno/tool_lint.go | 43 +----- gnovm/cmd/gno/tool_lint_test.go | 2 +- gnovm/pkg/gnolang/gotypecheck.go | 138 ++++++++++++------ gnovm/pkg/gnolang/gotypecheck_test.go | 2 +- gnovm/pkg/test/imports.go | 2 +- gnovm/stdlibs/generated.go | 81 ++++++++++ gnovm/stdlibs/std/emit_event_test.go | 2 +- gnovm/stdlibs/std/native_test.go | 2 +- gnovm/stdlibs/std/params_test.go | 2 +- gnovm/stdlibs/testing/testing.gno | 8 +- 14 files changed, 253 insertions(+), 110 deletions(-) diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index 8e25210f82e..ea2f8a0c319 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -3,6 +3,7 @@ package main import ( "fmt" "go/scanner" + "go/types" "io" "os" "path/filepath" @@ -18,12 +19,12 @@ type gnoCode string const ( gnoUnknownError gnoCode = "gnoUnknownError" - gnoReadError = "gnoReadError" - gnoImportError = "gnoImportError" - gnoGnoModError = "gnoGnoModError" - gnoPreprocessError = "gnoPreprocessError" - gnoParserError = "gnoParserError" - gnoTypeCheckError = "gnoTypeCheckError" + gnoReadError gnoCode = "gnoReadError" + gnoImportError gnoCode = "gnoImportError" + gnoGnoModError gnoCode = "gnoGnoModError" + gnoPreprocessError gnoCode = "gnoPreprocessError" + gnoParserError gnoCode = "gnoParserError" + gnoTypeCheckError gnoCode = "gnoTypeCheckError" // TODO: add new gno codes here. ) @@ -109,24 +110,63 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { switch err := err.(type) { case *gno.PreprocessError: err2 := err.Unwrap() - fmt.Fprintln(w, issueFromError( + // XXX probably no need for guessing, replace with exact issue. + fmt.Fprintln(w, guessIssueFromError( dir, pkgPath, err2, gnoPreprocessError).String()) case gno.ImportError: - fmt.Fprintln(w, issueFromError( - dir, pkgPath, err, gnoImportError).String()) + // NOTE: gnovm/pkg/test.LoadImport will return a + // ImportNotFoundError with format ": unknown import path: + // ", while gimp.ImportFrom() doesn't know so + // returns a ImportNotFoundError with format "unknown import + // path: "; but Go .Check ends up returning a types.Error + // instead, as seen in the hack in the next clause. So + // test.LoadImport needs this and guessing isn't needed. + fmt.Fprintln(w, gnoIssue{ + Code: gnoImportError, + Msg: err.GetMsg(), + Confidence: 1, + Location: err.GetLocation(), + }) + case types.Error: + loc := err.Fset.Position(err.Pos).String() + loc = replaceWithDirPath(loc, pkgPath, dir) + code := gnoTypeCheckError + if strings.Contains(err.Msg, "(unknown import path \"") { + // NOTE: This is a bit of a hack. + // See gimp.ImportFrom() comment on ImportNotFoundError + // on why this is necessary, and how to make it less hacky. + code = gnoImportError + } + fmt.Fprintln(w, gnoIssue{ + Code: code, + Msg: err.Msg, + Confidence: 1, + Location: loc, + }) case scanner.ErrorList: for _, err := range err { - fmt.Fprintln(w, issueFromError( - dir, - pkgPath, - err, - gnoParserError, - ).String()) + loc := err.Pos.String() + loc = replaceWithDirPath(loc, pkgPath, dir) + fmt.Fprintln(w, gnoIssue{ + Code: gnoParserError, + Msg: err.Msg, + Confidence: 1, + Location: loc, + }) } + case scanner.Error: + loc := err.Pos.String() + loc = replaceWithDirPath(loc, pkgPath, dir) + fmt.Fprintln(w, gnoIssue{ + Code: gnoParserError, + Msg: err.Msg, + Confidence: 1, + Location: loc, + }) default: // error type errors := multierr.Errors(err) if len(errors) == 1 { - fmt.Fprintln(w, issueFromError( + fmt.Fprintln(w, guessIssueFromError( dir, pkgPath, err, @@ -160,7 +200,7 @@ func catchPanic(dir, pkgPath string, stderr io.WriteCloser, action func()) (didP return } -func issueFromError(dir, pkgPath string, err error, code gnoCode) gnoIssue { +func guessIssueFromError(dir, pkgPath string, err error, code gnoCode) gnoIssue { var issue gnoIssue issue.Confidence = 1 issue.Code = code diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 3577a3bc525..8f44109b08a 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -248,7 +248,8 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore) if errs != nil { didError = true - io.ErrPrintln(errs) + // already printed in lintTypeCheck. + // io.ErrPrintln(errs) return } } else if cmd.verbose { diff --git a/gnovm/cmd/gno/testdata/lint/bad_import.txtar b/gnovm/cmd/gno/testdata/lint/bad_import.txtar index 944891da1ce..f8214ba8f1f 100644 --- a/gnovm/cmd/gno/testdata/lint/bad_import.txtar +++ b/gnovm/cmd/gno/testdata/lint/bad_import.txtar @@ -19,4 +19,4 @@ module gno.land/p/test -- stdout.golden -- -- stderr.golden -- -bad_file.gno:3:8: unknown import path python (code=gnoImportError) +bad_file.gno:3:8: unknown import path "python" (code=gnoImportError) diff --git a/gnovm/cmd/gno/testdata/test/unknown_package.txtar b/gnovm/cmd/gno/testdata/test/unknown_package.txtar index bc603bc418b..de70adf426f 100644 --- a/gnovm/cmd/gno/testdata/test/unknown_package.txtar +++ b/gnovm/cmd/gno/testdata/test/unknown_package.txtar @@ -4,7 +4,7 @@ ! stdout .+ # XXX catch and convert to gnoImportError -stderr 'contract.gno:3:8: could not import foobarbaz \(import not found: foobarbaz\) \(code=gnoUnknownError\)' +stderr 'contract.gno:3:8: could not import foobarbaz \(unknown import path "foobarbaz"\) \(code=gnoImportError\)' -- contract.gno -- package contract diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index b72f7281ca3..84eab07ac34 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -6,7 +6,6 @@ import ( "flag" "fmt" "go/ast" - "go/scanner" "go/token" "go/types" goio "io" @@ -151,16 +150,16 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { - io.ErrPrintln(issueFromError( - dir, pkgPath, err, gnoReadError).String()) + printError(io.Err(), dir, pkgPath, err) hasError = true continue } // Perform imports using the parent store. if err := test.LoadImports(ts, mpkg); err != nil { - io.ErrPrintln(issueFromError( - dir, pkgPath, err, gnoImportError).String()) + // io.ErrPrintln(guessIssueFromError( + // dir, pkgPath, err, gnoImportError).String()) + printError(io.Err(), dir, pkgPath, err) hasError = true continue } @@ -278,39 +277,7 @@ func lintTypeCheck( // Print errors, and return the first unexpected error. errors := multierr.Errors(tcErrs) for _, err := range errors { - switch err := err.(type) { - case types.Error: - loc := err.Fset.Position(err.Pos).String() - loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(gnoIssue{ - Code: gnoTypeCheckError, - Msg: err.Msg, - Confidence: 1, - Location: loc, - }) - case scanner.ErrorList: - for _, scErr := range err { - loc := scErr.Pos.String() - loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(gnoIssue{ - Code: gnoParserError, - Msg: scErr.Msg, - Confidence: 1, - Location: loc, - }) - } - case scanner.Error: - loc := err.Pos.String() - loc = replaceWithDirPath(loc, mpkg.Path, dir) - io.ErrPrintln(gnoIssue{ - Code: gnoParserError, - Msg: err.Msg, - Confidence: 1, - Location: loc, - }) - default: - panic(err) // unexpected. - } + printError(io.Err(), dir, mpkg.Path, err) } lerr = tcErrs diff --git a/gnovm/cmd/gno/tool_lint_test.go b/gnovm/cmd/gno/tool_lint_test.go index 7a45e8cdb1c..f7520c3718e 100644 --- a/gnovm/cmd/gno/tool_lint_test.go +++ b/gnovm/cmd/gno/tool_lint_test.go @@ -54,7 +54,7 @@ func TestLintApp(t *testing.T) { }, { args: []string{"lint", "../../tests/integ/invalid_gno_file/"}, - stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=gnoReadError)", + stderrShouldContain: "../../tests/integ/invalid_gno_file/invalid.gno:1:1: expected 'package', found packag (code=gnoParserError)", errShouldBe: "exit code: 1", }, { diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 0158e436244..434b3c817ac 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -68,7 +68,7 @@ type gnoImporter struct { getter MemPackageGetter cache map[string]*gnoImporterResult cfg *types.Config - errors error // multierr + errors []error // there may be many for a single import stack []string // stack of pkgpaths for cyclic import detection } @@ -79,39 +79,45 @@ func (gimp *gnoImporter) Import(path string) (*types.Package, error) { // Pass through to cfg.Error for collecting all type-checking errors. func (gimp *gnoImporter) Error(err error) { - gimp.errors = multierr.Append(gimp.errors, err) + gimp.errors = append(gimp.errors, err) } // ImportFrom returns the imported package for the given import // pkgPath when imported by a package file located in dir. func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*types.Package, error) { if result, ok := gimp.cache[pkgPath]; ok { - if gimp.pkgPath == pkgPath { - // continue: xxx_test importing self. - } else if result.pending { + if result.pending { idx := slices.Index(gimp.stack, pkgPath) - loop := gimp.stack[idx:] - err := ImportCycleError(loop) + cycle := gimp.stack[idx:] + err := ImportCycleError{Cycle: cycle} + // NOTE: see comment below for ImportNotFoundError. + // gimp.importErrors = append(gimp.importErrors, err) result.err = err - // NOTE: returning an error loses type info? - // return nil, ImportCycleError(loop) - panic(err) - } else if gimp.pkgPath == pkgPath { - // continue: xxx_test importing self. + return nil, err } else { return result.pkg, result.err } } - gimp.cache[pkgPath] = &gnoImporterResult{pending: true} + result := &gnoImporterResult{pending: true} + gimp.cache[pkgPath] = result gimp.stack = append(gimp.stack, pkgPath) - defer func() { gimp.stack = gimp.stack[:len(gimp.stack)-1] }() + defer func() { + gimp.stack = gimp.stack[:len(gimp.stack)-1] + }() mpkg := gimp.getter.GetMemPackage(pkgPath) if mpkg == nil { - err := ImportNotFoundError(pkgPath) - gimp.cache[pkgPath] = &gnoImporterResult{err: err} - // NOTE: returning an error loses type info? - // return nil, err - panic(err) + err := ImportNotFoundError{PkgPath: pkgPath} + // NOTE: When returning an err, Go will strip type information. + // When panic'd, the type information will be preserved, but + // the file location information will be lost. Therefore, + // return the error but later in printError() parse the message + // and recast to a gnoImportError. + // TODO: For completeness we could append to a separate slice + // and check presence in gimp.importErrors before converting. + // gimp.importErrors = append(gimp.importErrors, err) + result.err = err + result.pending = false + return nil, err } pmode := ParseModeProduction // don't parse test files for imports... if gimp.pkgPath == pkgPath { @@ -122,12 +128,13 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ strict := false // don't check for gno.mod for imports. pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, pmode, strict) if errs != nil { - // NOTE: - // Returning an error doesn't abort the type-checker. - // Panic instead to quit quickly. - panic(errs) + result.err = errs + result.pending = false + return nil, errs } - gimp.cache[pkgPath] = &gnoImporterResult{pkg: pkg, err: errs, pending: false} + result.pkg = pkg + result.err = nil + result.pending = false return pkg, errs } @@ -189,13 +196,22 @@ type realm interface{} // shim panic("error parsing gotypecheck gnobuiltins.go file") } + // NOTE: When returning errs from this function, + // STEP 4: Type-check Gno0.9 AST in Go (normal, and _test.gno if ParseModeIntegration). gofs = append(gofs, gmgof) + // NOTE: .Check doesn't return an err, it appends to .errors. also, + // gimp.errors may already be populated. For example, even after an + // import failure the Go type checker will continue to try to import + // more imports, to collect more errors for the user to see. + numErrs := len(gimp.errors) pkg, _ = gimp.cfg.Check(mpkg.Path, gofset, gofs, nil) - if gimp.errors != nil { - errs = gimp.errors + /* NOTE: Uncomment to fail earlier. + if len(gimp.errors) != numErrs { + errs = multierr.Combine(gimp.errors...) return } + */ // STEP 4: Type-check Gno0.9 AST in Go (xxx_test package if ParseModeAll). if strings.HasSuffix(mpkg.Name, "_test") { @@ -206,10 +222,12 @@ type realm interface{} // shim } _gofs2 := append(_gofs, gmgof) _, _ = gimp.cfg.Check(mpkg.Path, gofset, _gofs2, nil) - if gimp.errors != nil { - errs = gimp.errors + /* NOTE: Uncomment to fail earlier. + if len(gimp.errors) != numErrs { + errs = multierr.Combine(gimp.errors...) return } + */ // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if ParseModeAll). // Each filetest is its own package. @@ -218,12 +236,14 @@ type realm interface{} // shim gmgof.Name = tgof.Name // may be anything. tgof2 := []*ast.File{gmgof, tgof} _, _ = gimp.cfg.Check(mpkg.Path, gofset, tgof2, nil) - if gimp.errors != nil { - errs = gimp.errors + /* NOTE: Uncomment to fail earlier. + if len(gimp.errors) != numErrs { + errs = multierr.Combine(gimp.errors...) return } + */ } - return pkg, gofset, gofs, _gofs, tgofs, gimp.errors + return pkg, gofset, gofs, _gofs, tgofs, multierr.Combine(gimp.errors[numErrs:]...) } func deleteOldIdents(idents map[string]func(), gof *ast.File) { @@ -253,27 +273,55 @@ func deleteOldIdents(idents map[string]func(), gof *ast.File) { //---------------------------------------- // Errors -type ImportNotFoundError string - -func (e ImportNotFoundError) Error() string { - return "import not found: " + string(e) -} - -type ImportCycleError []string - -func (e ImportCycleError) Error() string { - return fmt.Sprintf("cyclic import detected: %s -> %s", strings.Join(e, " -> "), e[0]) -} - +// ImportError is an interface type. type ImportError interface { assertImportError() error + GetLocation() string + GetMsg() string } func (e ImportNotFoundError) assertImportError() {} func (e ImportCycleError) assertImportError() {} var ( - _ ImportError = ImportNotFoundError("") - _ ImportError = ImportCycleError(nil) + _ ImportError = ImportNotFoundError{} + _ ImportError = ImportCycleError{} ) + +// ImportNotFoundError implements ImportError +type ImportNotFoundError struct { + Location string + PkgPath string +} + +func (e ImportNotFoundError) GetLocation() string { return e.Location } + +func (e ImportNotFoundError) GetMsg() string { return fmt.Sprintf("unknown import path %q", e.PkgPath) } + +func (e ImportNotFoundError) Error() string { return importErrorString(e) } + +// ImportCycleError implements ImportError +type ImportCycleError struct { + Location string + Cycle []string +} + +func (e ImportCycleError) GetLocation() string { return e.Location } + +func (e ImportCycleError) GetMsg() string { + return fmt.Sprintf("cyclic import detected: %s -> %s", strings.Join(e.Cycle, " -> "), e.Cycle[0]) +} + +func (e ImportCycleError) Error() string { return importErrorString(e) } + +// helper +func importErrorString(err ImportError) string { + loc := err.GetLocation() + msg := err.GetMsg() + if loc != "" { + return loc + ": " + msg + } else { + return msg + } +} diff --git a/gnovm/pkg/gnolang/gotypecheck_test.go b/gnovm/pkg/gnolang/gotypecheck_test.go index e24812353d4..8bb382f6931 100644 --- a/gnovm/pkg/gnolang/gotypecheck_test.go +++ b/gnovm/pkg/gnolang/gotypecheck_test.go @@ -174,7 +174,7 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, mockPackageGetter{}, - errContains("import not found: std"), + errContains("unknown import path \"std\""), }, { "ImportSucceeded", diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index c88161546af..96c99dccd65 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -264,7 +264,7 @@ func LoadImports(store gno.Store, mpkg *std.MemPackage) (err error) { } pkg := store.GetPackage(imp.PkgPath, true) if pkg == nil { - return fmt.Errorf("%v: unknown import path %v", fset.Position(imp.Spec.Pos()).String(), imp.PkgPath) + return gno.ImportNotFoundError{Location: fset.Position(imp.Spec.Pos()).String(), PkgPath: imp.PkgPath} } } return nil diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index a474f75d622..c8253148820 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -13,6 +13,7 @@ import ( libs_runtime "github.com/gnolang/gno/gnovm/stdlibs/runtime" libs_std "github.com/gnolang/gno/gnovm/stdlibs/std" libs_sys_params "github.com/gnolang/gno/gnovm/stdlibs/sys/params" + libs_testing "github.com/gnolang/gno/gnovm/stdlibs/testing" libs_testing_base "github.com/gnolang/gno/gnovm/stdlibs/testing/base" libs_time "github.com/gnolang/gno/gnovm/stdlibs/time" ) @@ -1134,6 +1135,86 @@ var nativeFuncs = [...]NativeFunc{ p0, p1, p2, p3) }, }, + { + "testing", + "matchString", + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("p0"), Type: gno.X("string")}, + {NameExpr: *gno.Nx("p1"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("bool")}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + false, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() + ) + + tv0 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV + tv0.DeepFill(m.Store) + gno.Gno2GoValue(tv0, rp0) + tv1 := b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV + tv1.DeepFill(m.Store) + gno.Gno2GoValue(tv1, rp1) + + r0, r1 := libs_testing.X_matchString(p0, p1) + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, + { + "testing", + "recoverWithStacktrace", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.AnyT()}, + {NameExpr: *gno.Nx("r1"), Type: gno.X("string")}, + }, + false, + func(m *gno.Machine) { + r0, r1 := libs_testing.X_recoverWithStacktrace() + + m.PushValue(r0) + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r1).Elem(), + )) + }, + }, + { + "testing", + "unixNano", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{ + {NameExpr: *gno.Nx("r0"), Type: gno.X("int64")}, + }, + false, + func(m *gno.Machine) { + r0 := libs_testing.X_unixNano() + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + }, + }, { "testing/base", "unixNano", diff --git a/gnovm/stdlibs/std/emit_event_test.go b/gnovm/stdlibs/std/emit_event_test.go index 2bf25539b9d..7b4c8ae9d0e 100644 --- a/gnovm/stdlibs/std/emit_event_test.go +++ b/gnovm/stdlibs/std/emit_event_test.go @@ -2,7 +2,7 @@ package std import ( "encoding/json" - testing "testing/base" + "testing" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/sdk" diff --git a/gnovm/stdlibs/std/native_test.go b/gnovm/stdlibs/std/native_test.go index cd89e7aab1b..23f3d244aab 100644 --- a/gnovm/stdlibs/std/native_test.go +++ b/gnovm/stdlibs/std/native_test.go @@ -2,7 +2,7 @@ package std import ( "fmt" - testing "testing/base" + "testing" "github.com/stretchr/testify/assert" diff --git a/gnovm/stdlibs/std/params_test.go b/gnovm/stdlibs/std/params_test.go index 73f70af49c1..21de716e69b 100644 --- a/gnovm/stdlibs/std/params_test.go +++ b/gnovm/stdlibs/std/params_test.go @@ -1,7 +1,7 @@ package std import ( - testing "testing/base" + "testing" ) // XXX move elsewhere in the gno.land/ dir. diff --git a/gnovm/stdlibs/testing/testing.gno b/gnovm/stdlibs/testing/testing.gno index bbd88936894..00b1c041391 100644 --- a/gnovm/stdlibs/testing/testing.gno +++ b/gnovm/stdlibs/testing/testing.gno @@ -5,7 +5,13 @@ import ( "testing/base" ) -// XXX everything actually declared in testing/base +// NOTE almost everything actually declared in testing/base + +// NOTE These native functions are duplicated in testing and testing/base, +// and also all overridden in test/stdlibs/testing and test/stdlibs/testing/base. +func matchString(pat, str string) (bool, string) +func recoverWithStacktrace() (interface{}, string) +func unixNano() int64 // ---------------------------------------- // Top level functions From 113825eb7ec61f3ed025607fc7106ddf6c8d75dc Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 18 May 2025 19:18:17 -0700 Subject: [PATCH 36/83] gno fix --- gnovm/adr/pr4264_lint_transpile.md | 14 +- gnovm/cmd/gno/main.go | 2 +- gnovm/cmd/gno/tool_fix.go | 350 +++++++++++++++++++++++++++++ gnovm/cmd/gno/tool_lint.go | 21 +- 4 files changed, 373 insertions(+), 14 deletions(-) create mode 100644 gnovm/cmd/gno/tool_fix.go diff --git a/gnovm/adr/pr4264_lint_transpile.md b/gnovm/adr/pr4264_lint_transpile.md index 8f33c81b5f2..50b9f916079 100644 --- a/gnovm/adr/pr4264_lint_transpile.md +++ b/gnovm/adr/pr4264_lint_transpile.md @@ -10,7 +10,7 @@ The steps of Gno 0.0 --> Gno 0.9 transpiling. 9. `Transpile*()` Part 2: main Go AST mutations for Gno upgrade. 10. `mpkg.WriteTo()`: write mem package to disk. -In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: +In `cmd/gno/tool_fix.go` each step is grouped into three stages for all dirs: * Stage 1: (for all dirs) 1. `gno.ReadMemPackage()` 2. `gno.TypeCheckMemPackage()` > `ParseGnoMod() @@ -26,6 +26,18 @@ In `cmd/gno/tool_lint.go` each step is grouped into stages for all dirs: * Stage 3: 10. `mpkg.WriteTo()` +In `cmd/gno/tool_lint.go` each step is grouped into two stages for all dirs, +and some steps are omited as compared to `tool_fix.go`: + * Stage 1: (for all dirs) + 1. `gno.ReadMemPackage()` + 2. `gno.TypeCheckMemPackage()` > `ParseGnoMod() + 3. `gno.TypeCheckMemPackage()` > `GoParseMemPackage() + `gno.TypeCheckMemPackage()` > `g.cfg.Check() + 4. `sourceAndTestFileset()` > `gno.MustParseFile()` + 5. `tm.PreprocessFiles()` + * Stage 2: + 6. `mpkg.WriteTo()` + In `pkg/gnolang/gotypecheck.go`, `TypeCheck*()` diverges at step 4 and terminates: 1. `mpkg` provided as argument 2. `ParseGnoMod() diff --git a/gnovm/cmd/gno/main.go b/gnovm/cmd/gno/main.go index ae4559eb080..90c9540d4e4 100644 --- a/gnovm/cmd/gno/main.go +++ b/gnovm/cmd/gno/main.go @@ -28,7 +28,7 @@ func newGnocliCmd(io commands.IO) *commands.Command { newCleanCmd(io), newDocCmd(io), newEnvCmd(io), - // fix + newFixCmd(io), newFmtCmd(io), // generate // get diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go new file mode 100644 index 00000000000..afce2eb6d58 --- /dev/null +++ b/gnovm/cmd/gno/tool_fix.go @@ -0,0 +1,350 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "go/ast" + "go/token" + "go/types" + goio "io" + "io/fs" + "os" + "path" + "path/filepath" + + "github.com/gnolang/gno/gnovm/pkg/gnoenv" + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/test" + "github.com/gnolang/gno/tm2/pkg/commands" +) + +/* +Translate Interrealm Spec 2 to Interrealm Spec 3 (Gno 0.9) + + - Interrealm Spec 1: Original; every realm function is (automatically) + a crossing function. This was working for our examples and was + conceptually simple, but several problems were identified late in + development; + + 1. p package code copied over to r realms would behave differently + with respect to std.CurrentRealm() and std.PreviousRealm(). It will + become typical after launch that p code gets copied to r code for + cutstom patchces; and potential p code will first to be tested in + more mutable r realms. + + 2. a reentrancy issue exists where r realm's calls to some variable + function/method `var A func(...)...` are usually of functions + declared in external realms (such as callback functions expected to + be provided by the external realm) but instead ends up being a + function declared in the the same r realm, an expected realm + boundary isn't there, and may lead to exploits. + + - Interrealm Spec 2: With explicit cross(fn)(...) and crossing() + declarations. The previous problems were solved by explicit crossing() + declarations in realm functions (solves 1), and explicit + cross(fn)(...) calls (solves 2 for the most part). But more problems + were identified after most of the migration was done for examples from + spec 1 to spec 2: + + 3. a reentrancy issue where if calls to r realm's function/method + A() are usually expected to be done by external realms (creating a + realm boundary), but the external caller does things to get the r + realm to call its own A(), the expected realm boundary isn't created + and may lead to exploits. + + 3.A. As a more concrete example of problem 3, when a realm takes as + parameter a callback function `cb func(...)...` that isn't expected + to be a crossing function and thus not explicitly crossed into. An + external user or realm can then craft a function literal expression + that calls the aforementioned realm's crossing functions without an + explicit cross(fn)(...) call, thereby again dissolving a realm + function boundary where one should be. + + 4. Users didn't like the cross(fn)(...) syntax. + + - Interrealm Spec 3: With @cross decorator and `cur realm` first + argument type. Instead of declaring a crossing-function with + `crossing()` as the first statement the @cross decorator is used for + package/file level function/methods declarations. Function literals + can likewise be declared crossing by being wrapped like + cross(func(...)...{}). When calling from within the same realm + (without creating a realm boundary), the `cur` value is passed through + to the called function's via its first argument; but when a realm + boundary is intended, `nil` is passed in instead. This resolves + problem 3.A because a non-crossing function literal would not be + declared with the `cur realm` first argument, and thus a non-crossing + call of the same realm's crossing function would not be syntactically + possible. + +---------------------------------------- + +Also refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). +*/ + +type fixCmd struct { + verbose bool + rootDir string + autoGnomod bool + // min_confidence: minimum confidence of a problem to print it + // (default 0.8) auto-fix: apply suggested fixes automatically. +} + +func newFixCmd(io commands.IO) *commands.Command { + cmd := &fixCmd{} + + return commands.NewCommand( + commands.Metadata{ + Name: "fix", + ShortUsage: "fix [flags] [...]", + ShortHelp: "runs the fixer for the specified packages", + }, + cmd, + func(_ context.Context, args []string) error { + return execFix(cmd, args, io) + }, + ) +} + +func (c *fixCmd) RegisterFlags(fs *flag.FlagSet) { + rootdir := gnoenv.RootDir() + + fs.BoolVar(&c.verbose, "v", false, "verbose output when fixning") + fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)") + fs.BoolVar(&c.autoGnomod, "auto-gnomod", true, "auto-generate gno.mod file if not already present.") +} + +func execFix(cmd *fixCmd, args []string, io commands.IO) error { + // Show a help message by default. + if len(args) == 0 { + return flag.ErrHelp + } + + // Guess opts.RootDir. + if cmd.rootDir == "" { + cmd.rootDir = gnoenv.RootDir() + } + + dirs, err := gnoPackagesFromArgsRecursively(args) + if err != nil { + return fmt.Errorf("list packages from args: %w", err) + } + + hasError := false + + bs, ts := test.StoreWithOptions( + cmd.rootDir, goio.Discard, + test.StoreOptions{PreprocessOnly: true}, + ) + ppkgs := map[string]processedPackage{} + + if cmd.verbose { + io.ErrPrintfln("flinting directories: %v", dirs) + } + //---------------------------------------- + // FIX STAGE 1: Type-check and lint. + for _, dir := range dirs { + if cmd.verbose { + io.ErrPrintln("fixing %q", dir) + } + + // Only supports directories. + // You should fix all directories at once to avoid dependency issues. + info, err := os.Stat(dir) + if err == nil && !info.IsDir() { + dir = filepath.Dir(dir) + } + + // Read and parse gno.mod directly. + fpath := path.Join(dir, "gno.mod") + mod, err := gnomod.ParseFilepath(fpath) + if errors.Is(err, fs.ErrNotExist) { + if cmd.autoGnomod { + modstr := gno.GenGnoModDefault("gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx") + mod, err = gnomod.ParseBytes("gno.mod", []byte(modstr)) + if err != nil { + panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) + } + io.ErrPrintfln("auto-generated %q", fpath) + err = mod.WriteFile(fpath) + if err != nil { + panic(fmt.Errorf("unexpected panic writing to %q: %w", fpath, err)) + } + // err == nil. + } + } + if err != nil { + issue := gnoIssue{ + Code: gnoGnoModError, + Confidence: 1, // ?? + Location: fpath, + Msg: err.Error(), + } + io.ErrPrintln(issue) + hasError = true + return commands.ExitCodeError(1) + } + + // See adr/pr4264_fix_transpile.md + // FIX STEP 1: ReadMemPackage() + // Read MemPackage with pkgPath. + pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) + mpkg, err := gno.ReadMemPackage(dir, pkgPath) + if err != nil { + printError(io.Err(), dir, pkgPath, err) + hasError = true + continue + } + + // Perform imports using the parent store. + if err := test.LoadImports(ts, mpkg); err != nil { + printError(io.Err(), dir, pkgPath, err) + hasError = true + continue + } + + // Handle runtime errors + didPanic := catchPanic(dir, pkgPath, io.Err(), func() { + // Wrap in cache wrap so execution of the fixer + // doesn't impact other packages. + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + + // These are Go types. + var pn *gno.PackageNode + var _ *types.Package + var gofset *token.FileSet + var gofs, _gofs, tgofs []*ast.File + var errs error + + // Run type checking + // FIX STEP 2: ParseGnoMod() + // FIX STEP 3: GoParse*() + // + // lintTypeCheck(mpkg) --> + // TypeCheckMemPackage(mpkg) --> + // imp.typeCheckMemPackage(mpkg) + // ParseGnoMod(mpkg); + // GoParseMemPackage(mpkg); + // g.cmd.Check(); + if !mod.Draft { + _, gofset, gofs, _gofs, tgofs, errs = + lintTypeCheck(io, dir, mpkg, gs) + if errs != nil { + // io.ErrPrintln(errs) already printed. + hasError = true + return + } + } else if cmd.verbose { + io.ErrPrintfln("%s: module is draft, skipping type check", dir) + } + + // FIX STEP 4: Prepare*() + // Construct machine for preprocessing. + tm := test.Machine(gs, goio.Discard, pkgPath, false) + defer tm.Release() + + // Prepare Go AST for preprocessing. + if mod.GetGno() == "0.0" { + allgofs := append(gofs, _gofs...) + allgofs = append(allgofs, tgofs...) + errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) + if errs != nil { + io.ErrPrintln(errs) + hasError = true + return // Prepare must succeed. + } + } + + // FIX STEP 5: re-parse + // Gno parse source fileset and test filesets. + all, fset, _tests, ftests := sourceAndTestFileset(mpkg) + + // FIX STEP 6: PreprocessFiles() + // Preprocess fset files (w/ some _test.gno). + pn, _ = tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + // Preprocess _test files (all _test.gno). + for _, fset := range _tests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + } + // Preprocess _filetest.gno files. + for _, fset := range ftests { + tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false) + } + + // Record results. + ppkgs[dir] = processedPackage{ + mpkg, fset, pn, _tests, ftests} + + // FIX STEP 7: FindXforms(): + // FindXforms for all files if outdated. + if mod.GetGno() == "0.0" { + // Use the preprocessor to collect the + // transformations needed to be done. + // They are collected in + // pn.GetAttribute("XREALMFORM") + for _, fn := range all.Files { + gno.FindXformsGno0p9(gs, pn, fn) + } + } + }) + if didPanic { + hasError = true + } + } + if hasError { + return commands.ExitCodeError(1) + } + + //---------------------------------------- + // FIX STAGE 2: Transpile to Gno 0.9 + // Must be a separate stage because dirs depend on each other. + for _, dir := range dirs { + ppkg, ok := ppkgs[dir] + if !ok { + // XXX fix this; happens when fixing a file. + // XXX see comment on top of this file. + panic("missing package; gno fix currently only supports directories.") + } + mpkg, pn := ppkg.mpkg, ppkg.pn + + // If gno version is already 0.9, skip. + mod, err := gno.ParseCheckGnoMod(mpkg) + if mod.GetGno() == "0.9" { // XXX + continue + } + + // FIX STEP 8 & 9: gno.TranspileGno0p9() Part 1 & 2 + xforms1, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XFORMS).(map[string]struct{}) + err = gno.TranspileGno0p9(mpkg, dir, xforms1) + if err != nil { + return err + } + } + if hasError { + return commands.ExitCodeError(1) + } + + //---------------------------------------- + // FIX STAGE 3: Write. + // Must be a separate stage to prevent partial writes. + for _, dir := range dirs { + ppkg, ok := ppkgs[dir] + if !ok { + panic("where did it go") + } + + // FIX STEP 10: mpkg.WriteTo(): + err := ppkg.mpkg.WriteTo(dir) + if err != nil { + return err + } + } + + return nil +} diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 84eab07ac34..8ca0882e161 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -96,7 +96,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { io.ErrPrintfln("flinting directories: %v", dirs) } //---------------------------------------- - // STAGE 1: Lint. + // LINT STAGE 1: Typecheck and lint. for _, dir := range dirs { if cmd.verbose { io.ErrPrintfln("linting %q", dir) @@ -145,7 +145,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // See adr/pr4264_lint_transpile.md - // STEP 1: ReadMemPackage() + // LINT STEP 1: ReadMemPackage() // Read MemPackage with pkgPath. pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) @@ -157,8 +157,6 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Perform imports using the parent store. if err := test.LoadImports(ts, mpkg); err != nil { - // io.ErrPrintln(guessIssueFromError( - // dir, pkgPath, err, gnoImportError).String()) printError(io.Err(), dir, pkgPath, err) hasError = true continue @@ -176,7 +174,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { var errs error // Run type checking - // STEP 2: ParseGnoMod() + // LINT STEP 2: ParseGnoMod() // STEP 3: GoParse*() // // lintTypeCheck(mpkg) --> @@ -196,26 +194,25 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { io.ErrPrintfln("%s: module is draft, skipping type check", dir) } - // STEP 4: Prepare*() // Construct machine for testing. tm := test.Machine(gs, goio.Discard, pkgPath, false) defer tm.Release() - // STEP 5: re-parse + // LINT STEP 4: re-parse // Gno parse source fileset and test filesets. _, fset, _tests, ftests := sourceAndTestFileset(mpkg) - // STEP 6: PreprocessFiles() + // LINT STEP 5: PreprocessFiles() // Preprocess fset files (w/ some _test.gno). pn, _ = tm.PreprocessFiles( mpkg.Name, mpkg.Path, fset, false, false) - // STEP 6: PreprocessFiles() + // LINT STEP 5: PreprocessFiles() // Preprocess _test files (all _test.gno). for _, fset := range _tests { tm.PreprocessFiles( mpkg.Name, mpkg.Path, fset, false, false) } - // STEP 6: PreprocessFiles() + // LINT STEP 5: PreprocessFiles() // Preprocess _filetest.gno files. for _, fset := range ftests { tm.PreprocessFiles( @@ -236,7 +233,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } //---------------------------------------- - // STAGE 2: Write. + // LINT STAGE 2: Write. // Must be a separate stage to prevent partial writes. for _, dir := range dirs { ppkg, ok := ppkgs[dir] @@ -244,7 +241,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { panic("where did it go") } - // STEP 10: mpkg.WriteTo(): + // LINT STEP 6: mpkg.WriteTo(): err := ppkg.mpkg.WriteTo(dir) if err != nil { return err From 7f280ba7c6cec233a6b950f5a3015cb169123163 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 18 May 2025 21:25:54 -0700 Subject: [PATCH 37/83] fix tests related to span/location StringXXX(). --- gnovm/pkg/gnolang/gno_test.go | 50 +++++++++---------- gnovm/pkg/gnolang/go2gno.go | 12 ++--- gnovm/pkg/gnolang/nodes_span.go | 22 +++----- gnovm/pkg/gnolang/preprocess.go | 7 ++- gnovm/pkg/gnolang/type_check.go | 1 - gnovm/pkg/repl/repl_test.go | 2 +- gnovm/tests/files/access1.gno | 2 +- gnovm/tests/files/access4.gno | 2 +- gnovm/tests/files/access6.gno | 2 +- gnovm/tests/files/access7.gno | 2 +- gnovm/tests/files/add3.gno | 2 +- gnovm/tests/files/addressable_7a_err.gno | 2 +- gnovm/tests/files/addressable_7b_err.gno | 2 +- gnovm/tests/files/assign11.gno | 2 +- gnovm/tests/files/assign12.gno | 2 +- gnovm/tests/files/assign22.gno | 2 +- gnovm/tests/files/assign23.gno | 2 +- gnovm/tests/files/assign24.gno | 2 +- gnovm/tests/files/assign25.gno | 2 +- gnovm/tests/files/assign25b.gno | 2 +- gnovm/tests/files/assign25c.gno | 2 +- gnovm/tests/files/assign25d.gno | 2 +- gnovm/tests/files/assign26.gno | 2 +- gnovm/tests/files/assign27.gno | 2 +- gnovm/tests/files/assign28.gno | 2 +- gnovm/tests/files/assign29.gno | 2 +- gnovm/tests/files/assign30.gno | 2 +- gnovm/tests/files/assign31.gno | 2 +- gnovm/tests/files/assign33.gno | 2 +- gnovm/tests/files/assign35.gno | 2 +- gnovm/tests/files/assign37.gno | 2 +- gnovm/tests/files/assign37b.gno | 2 +- gnovm/tests/files/assign38.gno | 2 +- .../append/named_unnamed_type2_filetest.gno | 2 +- .../method/declaredType6_filetest.gno | 2 +- .../method/declaredType6b_filetest.gno | 2 +- .../more/assgin_two_filetest.gno | 2 +- .../more/return_interface1_filetest.gno | 2 +- .../more/return_interface_filetest.gno | 2 +- .../unnamedtype0b_filetest.gno | 2 +- gnovm/tests/files/blankidentifier0.gno | 2 +- gnovm/tests/files/blankidentifier2.gno | 2 +- gnovm/tests/files/blankidentifier3.gno | 2 +- gnovm/tests/files/blankidentifier6.gno | 2 +- gnovm/tests/files/block2.gno | 2 +- gnovm/tests/files/bltn0.gno | 2 +- gnovm/tests/files/bool6.gno | 2 +- gnovm/tests/files/break0.gno | 2 +- gnovm/tests/files/circular_constant.gno | 2 +- gnovm/tests/files/const23.gno | 2 +- gnovm/tests/files/const25.gno | 2 +- gnovm/tests/files/const26.gno | 2 +- gnovm/tests/files/const27.gno | 2 +- gnovm/tests/files/const28.gno | 2 +- gnovm/tests/files/const29.gno | 2 +- gnovm/tests/files/const30.gno | 2 +- gnovm/tests/files/const31.gno | 2 +- gnovm/tests/files/const32.gno | 2 +- gnovm/tests/files/const33.gno | 2 +- gnovm/tests/files/const34.gno | 2 +- gnovm/tests/files/const35.gno | 2 +- gnovm/tests/files/const36.gno | 2 +- gnovm/tests/files/const37_native.gno | 2 +- gnovm/tests/files/const37_stdlibs.gno | 2 +- gnovm/tests/files/const38.gno | 2 +- gnovm/tests/files/const39.gno | 2 +- gnovm/tests/files/const40.gno | 2 +- gnovm/tests/files/const41.gno | 2 +- gnovm/tests/files/const43.gno | 2 +- gnovm/tests/files/const44.gno | 2 +- gnovm/tests/files/const45_b.gno | 2 +- gnovm/tests/files/const48.gno | 2 +- gnovm/tests/files/const50.gno | 2 +- gnovm/tests/files/const55.gno | 2 +- gnovm/tests/files/const55a.gno | 2 +- gnovm/tests/files/const60.gno | 2 +- gnovm/tests/files/const61.gno | 2 +- gnovm/tests/files/const9.gno | 2 +- gnovm/tests/files/cont3.gno | 2 +- gnovm/tests/files/convert4.gno | 2 +- gnovm/tests/files/convert5.gno | 2 +- gnovm/tests/files/convert6.gno | 2 +- gnovm/tests/files/convert6a.gno | 2 +- gnovm/tests/files/convert6b.gno | 2 +- gnovm/tests/files/convert6c.gno | 2 +- gnovm/tests/files/convert6d.gno | 2 +- gnovm/tests/files/convert6e.gno | 2 +- gnovm/tests/files/convert7.gno | 2 +- gnovm/tests/files/convert7a.gno | 2 +- gnovm/tests/files/convert7b.gno | 2 +- gnovm/tests/files/float0.gno | 2 +- gnovm/tests/files/for21.gno | 2 +- gnovm/tests/files/for22.gno | 2 +- gnovm/tests/files/for23.gno | 2 +- gnovm/tests/files/for24.gno | 2 +- gnovm/tests/files/for7.gno | 2 +- gnovm/tests/files/fun21.gno | 2 +- gnovm/tests/files/fun22.gno | 2 +- gnovm/tests/files/fun23.gno | 2 +- gnovm/tests/files/fun24.gno | 2 +- gnovm/tests/files/fun25.gno | 2 +- gnovm/tests/files/fun27.gno | 2 +- gnovm/tests/files/fun28.gno | 2 +- gnovm/tests/files/govdao/realm_govdao.gno | 2 +- gnovm/tests/files/if2.gno | 2 +- gnovm/tests/files/import10.gno | 2 +- gnovm/tests/files/import11.gno | 2 +- gnovm/tests/files/import12.gno | 2 +- gnovm/tests/files/import13.gno | 2 +- gnovm/tests/files/import13b.gno | 2 +- gnovm/tests/files/import6.gno | 2 +- gnovm/tests/files/init1.gno | 2 +- gnovm/tests/files/interface47.gno | 2 +- gnovm/tests/files/invalid_labels0.gno | 2 +- gnovm/tests/files/invalid_labels2.gno | 2 +- gnovm/tests/files/native0.gno | 2 +- gnovm/tests/files/op7.gno | 2 +- gnovm/tests/files/overflow10.gno | 2 +- gnovm/tests/files/overflow11.gno | 2 +- gnovm/tests/files/overflow12.gno | 2 +- gnovm/tests/files/overflow13.gno | 2 +- gnovm/tests/files/overflow14.gno | 2 +- gnovm/tests/files/overflow16.gno | 2 +- gnovm/tests/files/overflow6.gno | 2 +- gnovm/tests/files/overflow7.gno | 2 +- gnovm/tests/files/overflow8.gno | 2 +- gnovm/tests/files/overflow9.gno | 2 +- gnovm/tests/files/pkgname1.gno | 2 +- gnovm/tests/files/ptr10.gno | 2 +- gnovm/tests/files/ptr9.gno | 2 +- gnovm/tests/files/range8.gno | 2 +- gnovm/tests/files/recursive1.gno | 2 +- gnovm/tests/files/recursive1c.gno | 2 +- gnovm/tests/files/recursive1d.gno | 2 +- gnovm/tests/files/recursive1f.gno | 2 +- gnovm/tests/files/recursive2.gno | 2 +- gnovm/tests/files/recursive2c.gno | 2 +- gnovm/tests/files/recursive4a.gno | 2 +- gnovm/tests/files/recursive5.gno | 2 +- gnovm/tests/files/recursive6a.gno | 2 +- gnovm/tests/files/recursive7a.gno | 2 +- gnovm/tests/files/recursive8.gno | 2 +- gnovm/tests/files/recursive9.gno | 2 +- gnovm/tests/files/recursive9a.gno | 2 +- gnovm/tests/files/recursive9b.gno | 2 +- gnovm/tests/files/recursive9c.gno | 2 +- gnovm/tests/files/recursive9d.gno | 2 +- gnovm/tests/files/redeclaration9.gno | 2 +- gnovm/tests/files/slice3.gno | 2 +- gnovm/tests/files/switch13.gno | 2 +- gnovm/tests/files/switch19.gno | 2 +- gnovm/tests/files/switch8.gno | 2 +- gnovm/tests/files/switch8b.gno | 2 +- gnovm/tests/files/switch8c.gno | 2 +- gnovm/tests/files/switch9.gno | 2 +- gnovm/tests/files/type30.gno | 2 +- gnovm/tests/files/type31.gno | 2 +- gnovm/tests/files/type32.gno | 2 +- gnovm/tests/files/type37.gno | 2 +- gnovm/tests/files/type37b.gno | 2 +- gnovm/tests/files/type37d.gno | 2 +- gnovm/tests/files/type37e.gno | 2 +- gnovm/tests/files/type37f.gno | 2 +- gnovm/tests/files/type39.gno | 2 +- gnovm/tests/files/type39a.gno | 2 +- gnovm/tests/files/type39b.gno | 2 +- gnovm/tests/files/type41.gno | 2 +- gnovm/tests/files/typeassert3.gno | 2 +- gnovm/tests/files/typeassert8.gno | 2 +- gnovm/tests/files/typeassert8a.gno | 2 +- gnovm/tests/files/typeassert9a.gno | 2 +- gnovm/tests/files/types/add_a0.gno | 2 +- gnovm/tests/files/types/add_a1.gno | 2 +- gnovm/tests/files/types/add_assign_a0.gno | 2 +- gnovm/tests/files/types/add_assign_a1.gno | 2 +- gnovm/tests/files/types/add_assign_a_01.gno | 2 +- gnovm/tests/files/types/add_assign_b0.gno | 2 +- gnovm/tests/files/types/add_assign_e0.gno | 2 +- gnovm/tests/files/types/add_assign_f0.gno | 2 +- gnovm/tests/files/types/add_assign_f1.gno | 2 +- gnovm/tests/files/types/add_assign_f2.gno | 2 +- gnovm/tests/files/types/add_assign_f3.gno | 2 +- gnovm/tests/files/types/add_b2.gno | 2 +- gnovm/tests/files/types/add_d4.gno | 2 +- gnovm/tests/files/types/add_e0.gno | 2 +- gnovm/tests/files/types/add_f0.gno | 2 +- gnovm/tests/files/types/add_f1.gno | 2 +- gnovm/tests/files/types/add_f2.gno | 2 +- gnovm/tests/files/types/and_a0.gno | 2 +- gnovm/tests/files/types/and_a1.gno | 2 +- gnovm/tests/files/types/and_b2.gno | 2 +- gnovm/tests/files/types/and_b3.gno | 2 +- gnovm/tests/files/types/and_d0.gno | 2 +- gnovm/tests/files/types/and_d4.gno | 2 +- gnovm/tests/files/types/and_e0.gno | 2 +- gnovm/tests/files/types/and_f0.gno | 2 +- gnovm/tests/files/types/and_f1.gno | 2 +- gnovm/tests/files/types/and_f2.gno | 2 +- gnovm/tests/files/types/assign_call.gno | 2 +- gnovm/tests/files/types/assign_index.gno | 2 +- gnovm/tests/files/types/assign_index_a.gno | 2 +- gnovm/tests/files/types/assign_index_b.gno | 2 +- gnovm/tests/files/types/assign_index_c.gno | 2 +- gnovm/tests/files/types/assign_literal.gno | 2 +- gnovm/tests/files/types/assign_literal10a.gno | 2 +- gnovm/tests/files/types/assign_literal11.gno | 2 +- gnovm/tests/files/types/assign_literal2.gno | 2 +- gnovm/tests/files/types/assign_literal3.gno | 2 +- gnovm/tests/files/types/assign_literal4.gno | 2 +- gnovm/tests/files/types/assign_literal5.gno | 2 +- gnovm/tests/files/types/assign_literal6.gno | 2 +- gnovm/tests/files/types/assign_literal7c.gno | 2 +- gnovm/tests/files/types/assign_nil.gno | 2 +- gnovm/tests/files/types/assign_nil2.gno | 2 +- gnovm/tests/files/types/assign_range_a.gno | 2 +- gnovm/tests/files/types/assign_range_a1.gno | 2 +- gnovm/tests/files/types/assign_range_b.gno | 2 +- gnovm/tests/files/types/assign_range_b1.gno | 2 +- gnovm/tests/files/types/assign_range_c.gno | 2 +- gnovm/tests/files/types/assign_range_d.gno | 2 +- gnovm/tests/files/types/assign_range_e.gno | 2 +- gnovm/tests/files/types/assign_rune_a.gno | 2 +- .../files/types/assign_type_assertion.gno | 2 +- .../files/types/assign_type_assertion_b.gno | 2 +- .../files/types/assign_type_assertion_c.gno | 2 +- .../files/types/assign_type_assertion_d.gno | 2 +- .../files/types/assign_type_assertion_e.gno | 2 +- .../files/types/assign_type_assertion_f.gno | 2 +- .../files/types/assign_type_assertion_g.gno | 2 +- gnovm/tests/files/types/bigdec2.gno | 2 +- gnovm/tests/files/types/bigdec5.gno | 2 +- gnovm/tests/files/types/bigdec_6.gno | 2 +- gnovm/tests/files/types/cmp_array_b.gno | 2 +- gnovm/tests/files/types/cmp_array_c.gno | 2 +- gnovm/tests/files/types/cmp_iface_5.gno | 2 +- .../tests/files/types/cmp_iface_5_stdlibs.gno | 2 +- gnovm/tests/files/types/cmp_pointer.gno | 2 +- gnovm/tests/files/types/cmp_primitive_1.gno | 2 +- gnovm/tests/files/types/cmp_slice_4.gno | 2 +- gnovm/tests/files/types/cmp_struct_a.gno | 2 +- gnovm/tests/files/types/cmp_struct_b.gno | 2 +- gnovm/tests/files/types/cmp_struct_c.gno | 2 +- gnovm/tests/files/types/cmp_struct_c1.gno | 2 +- gnovm/tests/files/types/cmp_struct_d.gno | 2 +- gnovm/tests/files/types/cmp_struct_e.gno | 2 +- gnovm/tests/files/types/cmp_struct_g.gno | 2 +- gnovm/tests/files/types/eql_0a0.gno | 2 +- gnovm/tests/files/types/eql_0a01.gno | 2 +- gnovm/tests/files/types/eql_0a02.gno | 2 +- gnovm/tests/files/types/eql_0a03.gno | 2 +- gnovm/tests/files/types/eql_0a1.gno | 2 +- gnovm/tests/files/types/eql_0a1a0.gno | 2 +- gnovm/tests/files/types/eql_0a1a1.gno | 2 +- gnovm/tests/files/types/eql_0a1f.gno | 2 +- gnovm/tests/files/types/eql_0a1g.gno | 2 +- gnovm/tests/files/types/eql_0a2.gno | 2 +- gnovm/tests/files/types/eql_0a3.gno | 2 +- gnovm/tests/files/types/eql_0a4.gno | 2 +- gnovm/tests/files/types/eql_0b2.gno | 2 +- gnovm/tests/files/types/eql_0b4.gno | 2 +- gnovm/tests/files/types/eql_0c2.gno | 2 +- gnovm/tests/files/types/eql_0e0.gno | 2 +- gnovm/tests/files/types/eql_0e1.gno | 2 +- gnovm/tests/files/types/eql_0f0.gno | 2 +- gnovm/tests/files/types/eql_0f1.gno | 2 +- gnovm/tests/files/types/eql_0f14.gno | 2 +- gnovm/tests/files/types/eql_0f16.gno | 2 +- gnovm/tests/files/types/eql_0f17.gno | 2 +- gnovm/tests/files/types/eql_0f20.gno | 2 +- gnovm/tests/files/types/eql_0f21.gno | 2 +- gnovm/tests/files/types/eql_0f27.gno | 2 +- gnovm/tests/files/types/eql_0f28.gno | 2 +- gnovm/tests/files/types/eql_0f29.gno | 2 +- gnovm/tests/files/types/eql_0f2b.gno | 2 +- gnovm/tests/files/types/eql_0f2c.gno | 2 +- gnovm/tests/files/types/eql_0f30.gno | 2 +- gnovm/tests/files/types/eql_0f30a.gno | 2 +- gnovm/tests/files/types/eql_0f30b.gno | 2 +- gnovm/tests/files/types/eql_0f30d.gno | 2 +- gnovm/tests/files/types/eql_0f30f.gno | 2 +- gnovm/tests/files/types/eql_0f30g.gno | 2 +- gnovm/tests/files/types/eql_0f41.gno | 2 +- gnovm/tests/files/types/eql_0f8.gno | 2 +- .../files/types/explicit_conversion_1.gno | 2 +- gnovm/tests/files/types/incdec_a1.gno | 2 +- gnovm/tests/files/types/incdec_a4.gno | 2 +- gnovm/tests/files/types/nil.gno | 2 +- gnovm/tests/files/types/or_a0.gno | 2 +- gnovm/tests/files/types/or_a1.gno | 2 +- gnovm/tests/files/types/or_b2.gno | 2 +- gnovm/tests/files/types/or_b3.gno | 2 +- gnovm/tests/files/types/or_d0.gno | 2 +- gnovm/tests/files/types/or_d4.gno | 2 +- gnovm/tests/files/types/or_e0.gno | 2 +- gnovm/tests/files/types/or_f0.gno | 2 +- gnovm/tests/files/types/or_f1.gno | 2 +- gnovm/tests/files/types/or_f2.gno | 2 +- gnovm/tests/files/types/rem_a0.gno | 2 +- gnovm/tests/files/types/rem_a1.gno | 2 +- gnovm/tests/files/types/rem_a2.gno | 2 +- gnovm/tests/files/types/rem_f3.gno | 2 +- gnovm/tests/files/types/runtime_a0.gno | 2 +- gnovm/tests/files/types/runtime_a3.gno | 2 +- gnovm/tests/files/types/shift_a11.gno | 2 +- gnovm/tests/files/types/shift_a14.gno | 2 +- gnovm/tests/files/types/shift_a15.gno | 2 +- gnovm/tests/files/types/shift_a16.gno | 2 +- gnovm/tests/files/types/shift_a3.gno | 2 +- gnovm/tests/files/types/shift_a7.gno | 2 +- gnovm/tests/files/types/shift_b6.gno | 2 +- gnovm/tests/files/types/shift_b7.gno | 2 +- gnovm/tests/files/types/shift_c6.gno | 2 +- gnovm/tests/files/types/shift_c7.gno | 2 +- gnovm/tests/files/types/shift_c8.gno | 2 +- gnovm/tests/files/types/shift_d12.gno | 2 +- gnovm/tests/files/types/shift_d13.gno | 2 +- gnovm/tests/files/types/shift_d27.gno | 2 +- gnovm/tests/files/types/shift_d28.gno | 2 +- gnovm/tests/files/types/shift_d32a.gno | 2 +- gnovm/tests/files/types/shift_d34.gno | 2 +- gnovm/tests/files/types/shift_d37.gno | 2 +- gnovm/tests/files/types/shift_d38.gno | 2 +- gnovm/tests/files/types/shift_d4.gno | 2 +- gnovm/tests/files/types/shift_d40.gno | 2 +- gnovm/tests/files/types/shift_d41.gno | 2 +- gnovm/tests/files/types/shift_d44.gno | 2 +- gnovm/tests/files/types/shift_d4a.gno | 2 +- gnovm/tests/files/types/shift_d5.gno | 2 +- gnovm/tests/files/types/shift_d50.gno | 2 +- gnovm/tests/files/types/shift_d51.gno | 2 +- gnovm/tests/files/types/shift_d54.gno | 2 +- gnovm/tests/files/types/shift_d56.gno | 2 +- gnovm/tests/files/types/shift_d5b.gno | 2 +- gnovm/tests/files/types/shift_e0.gno | 2 +- gnovm/tests/files/types/shift_e1.gno | 2 +- gnovm/tests/files/types/shift_e2.gno | 2 +- gnovm/tests/files/types/shift_e3.gno | 2 +- gnovm/tests/files/types/shift_e4.gno | 2 +- gnovm/tests/files/types/shift_e7.gno | 2 +- gnovm/tests/files/types/shift_e7a.gno | 2 +- gnovm/tests/files/types/shift_e7b.gno | 2 +- gnovm/tests/files/types/shift_e8.gno | 2 +- gnovm/tests/files/types/shift_f1b.gno | 2 +- gnovm/tests/files/types/shift_f2.gno | 2 +- gnovm/tests/files/types/shift_f2a.gno | 2 +- gnovm/tests/files/types/shift_f2b.gno | 2 +- gnovm/tests/files/types/shift_f2c.gno | 2 +- gnovm/tests/files/types/shift_f2d.gno | 2 +- gnovm/tests/files/types/shift_f3.gno | 2 +- gnovm/tests/files/types/shift_f3a.gno | 2 +- gnovm/tests/files/types/shift_f3b.gno | 2 +- gnovm/tests/files/types/shift_f3c.gno | 2 +- gnovm/tests/files/types/typed_nil_a.gno | 2 +- gnovm/tests/files/types/unary_a0c.gno | 2 +- gnovm/tests/files/types/unary_a2a.gno | 2 +- gnovm/tests/files/types/unary_a6.gno | 2 +- gnovm/tests/files/var18.gno | 2 +- gnovm/tests/files/var19.gno | 2 +- gnovm/tests/files/var20.gno | 2 +- gnovm/tests/files/var21.gno | 2 +- gnovm/tests/files/var22.gno | 2 +- gnovm/tests/files/var22b.gno | 2 +- gnovm/tests/files/var22c.gno | 2 +- gnovm/tests/files/var23.gno | 2 +- gnovm/tests/files/var24.gno | 2 +- gnovm/tests/files/var25.gno | 2 +- gnovm/tests/files/var26.gno | 2 +- gnovm/tests/files/var31.gno | 2 +- gnovm/tests/files/var32.gno | 2 +- gnovm/tests/files/var34.gno | 2 +- gnovm/tests/files/var34b.gno | 2 +- gnovm/tests/files/var34c.gno | 2 +- gnovm/tests/files/var35.gno | 2 +- 373 files changed, 407 insertions(+), 421 deletions(-) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 1a70c3e21f6..f1c573c43f4 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -171,7 +171,7 @@ func TestConvertTo(t *testing.T) { var g = float32(t) println(g) } - `, `test/main.go:5:12: cannot convert interface{} to float32: need type assertion`, + `, `test/main.go:5:12-22: cannot convert interface{} to float32: need type assertion`, }, { `package test @@ -181,7 +181,7 @@ func TestConvertTo(t *testing.T) { var g = int(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to int: need type assertion`, + `, `test/main.go:5:14-20: cannot convert interface{} to int: need type assertion`, }, { `package test @@ -191,7 +191,7 @@ func TestConvertTo(t *testing.T) { var g = int8(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to int8: need type assertion`, + `, `test/main.go:5:14-21: cannot convert interface{} to int8: need type assertion`, }, { `package test @@ -201,7 +201,7 @@ func TestConvertTo(t *testing.T) { var g = int16(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to int16: need type assertion`, + `, `test/main.go:5:14-22: cannot convert interface{} to int16: need type assertion`, }, { `package test @@ -211,7 +211,7 @@ func TestConvertTo(t *testing.T) { var g = int32(t) println(g) } - `, `test/main.go:5:16: cannot convert interface{} to int32: need type assertion`, + `, `test/main.go:5:16-24: cannot convert interface{} to int32: need type assertion`, }, { `package test @@ -221,7 +221,7 @@ func TestConvertTo(t *testing.T) { var g = int64(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to int64: need type assertion`, + `, `test/main.go:5:14-22: cannot convert interface{} to int64: need type assertion`, }, { `package test @@ -231,7 +231,7 @@ func TestConvertTo(t *testing.T) { var g = uint(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint: need type assertion`, + `, `test/main.go:5:14-21: cannot convert interface{} to uint: need type assertion`, }, { `package test @@ -241,7 +241,7 @@ func TestConvertTo(t *testing.T) { var g = uint8(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint8: need type assertion`, + `, `test/main.go:5:14-22: cannot convert interface{} to uint8: need type assertion`, }, { `package test @@ -251,7 +251,7 @@ func TestConvertTo(t *testing.T) { var g = uint16(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint16: need type assertion`, + `, `test/main.go:5:14-23: cannot convert interface{} to uint16: need type assertion`, }, { `package test @@ -261,7 +261,7 @@ func TestConvertTo(t *testing.T) { var g = uint32(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint32: need type assertion`, + `, `test/main.go:5:14-23: cannot convert interface{} to uint32: need type assertion`, }, { `package test @@ -271,7 +271,7 @@ func TestConvertTo(t *testing.T) { var g = uint64(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint64: need type assertion`, + `, `test/main.go:5:14-23: cannot convert interface{} to uint64: need type assertion`, }, // Built-in non-numeric types @@ -283,7 +283,7 @@ func TestConvertTo(t *testing.T) { var g = string(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to string: need type assertion`, + `, `test/main.go:5:14-23: cannot convert interface{} to string: need type assertion`, }, { `package test @@ -293,7 +293,7 @@ func TestConvertTo(t *testing.T) { var g = bool(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to bool: need type assertion`, + `, `test/main.go:5:14-21: cannot convert interface{} to bool: need type assertion`, }, { `package test @@ -303,7 +303,7 @@ func TestConvertTo(t *testing.T) { var g = rune(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to int32: need type assertion`, + `, `test/main.go:5:14-21: cannot convert interface{} to int32: need type assertion`, }, { `package test @@ -313,7 +313,7 @@ func TestConvertTo(t *testing.T) { var g = byte(t) println(g) } - `, `test/main.go:5:14: cannot convert interface{} to uint8: need type assertion`, + `, `test/main.go:5:14-21: cannot convert interface{} to uint8: need type assertion`, }, { @@ -325,7 +325,7 @@ func TestConvertTo(t *testing.T) { var g = MyInt(t) println(g) } - `, `test/main.go:6:14: cannot convert interface{} to test.MyInt: need type assertion`, + `, `test/main.go:6:14-22: cannot convert interface{} to test.MyInt: need type assertion`, }, { `package test @@ -334,7 +334,7 @@ func TestConvertTo(t *testing.T) { const a int = -1 println(uint(a)) }`, - `test/main.go:5:14: cannot convert constant of type IntKind to UintKind`, + `test/main.go:5:14-21: cannot convert constant of type IntKind to UintKind`, }, { `package test @@ -343,7 +343,7 @@ func TestConvertTo(t *testing.T) { const a int = -1 println(uint8(a)) }`, - `test/main.go:5:14: cannot convert constant of type IntKind to Uint8Kind`, + `test/main.go:5:14-22: cannot convert constant of type IntKind to Uint8Kind`, }, { `package test @@ -352,7 +352,7 @@ func TestConvertTo(t *testing.T) { const a int = -1 println(uint16(a)) }`, - `test/main.go:5:14: cannot convert constant of type IntKind to Uint16Kind`, + `test/main.go:5:14-23: cannot convert constant of type IntKind to Uint16Kind`, }, { `package test @@ -361,7 +361,7 @@ func TestConvertTo(t *testing.T) { const a int = -1 println(uint32(a)) }`, - `test/main.go:5:14: cannot convert constant of type IntKind to Uint32Kind`, + `test/main.go:5:14-23: cannot convert constant of type IntKind to Uint32Kind`, }, { `package test @@ -370,7 +370,7 @@ func TestConvertTo(t *testing.T) { const a int = -1 println(uint64(a)) }`, - `test/main.go:5:14: cannot convert constant of type IntKind to Uint64Kind`, + `test/main.go:5:14-23: cannot convert constant of type IntKind to Uint64Kind`, }, { `package test @@ -379,7 +379,7 @@ func TestConvertTo(t *testing.T) { const a float32 = 1.5 println(int32(a)) }`, - `test/main.go:5:14: cannot convert constant of type Float32Kind to Int32Kind`, + `test/main.go:5:14-22: cannot convert constant of type Float32Kind to Int32Kind`, }, { `package test @@ -387,7 +387,7 @@ func TestConvertTo(t *testing.T) { func main() { println(int32(1.5)) }`, - `test/main.go:4:14: cannot convert (const (1.5 bigdec)) to integer type`, + `test/main.go:4:14-24: cannot convert (const (1.5 bigdec)) to integer type`, }, { `package test @@ -396,7 +396,7 @@ func TestConvertTo(t *testing.T) { const a float64 = 1.5 println(int64(a)) }`, - `test/main.go:5:14: cannot convert constant of type Float64Kind to Int64Kind`, + `test/main.go:5:14-22: cannot convert constant of type Float64Kind to Int64Kind`, }, { `package test @@ -404,7 +404,7 @@ func TestConvertTo(t *testing.T) { func main() { println(int64(1.5)) }`, - `test/main.go:4:14: cannot convert (const (1.5 bigdec)) to integer type`, + `test/main.go:4:14-24: cannot convert (const (1.5 bigdec)) to integer type`, }, { `package test diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index a39f74f7178..38d0e451a31 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -138,21 +138,17 @@ func ParseFile(filename string, body string) (fn *FileNode, err error) { // setSpan() will not attempt to overwrite an existing span. // This usually happens when an inner node is passed outward, // in which case we want to keep the original specificity. -func setSpan(fs *token.FileSet, astn ast.Node, n Node) Node { +func setSpan(fs *token.FileSet, gon ast.Node, n Node) Node { if n.GetSpan().IsZero() { - pos := astn.Pos() - posn := fs.Position(pos) - end := astn.End() - endn := fs.Position(end) - n.SetSpan(Span{Pos: Pos{posn.Line, posn.Column}, End: Pos{endn.Line, endn.Column}}) + n.SetSpan(SpanFromGo(fs, gon)) } return n } -func sprintASTNode(fs *token.FileSet, astn ast.Node) string { +func sprintASTNode(fs *token.FileSet, gon ast.Node) string { // Write ast.Node as string. var buf bytes.Buffer - err := gofmt.Node(&buf, fs, astn) + err := gofmt.Node(&buf, fs, gon) if err != nil { panic(fmt.Errorf("stringifying ast.Node: %v", err)) } diff --git a/gnovm/pkg/gnolang/nodes_span.go b/gnovm/pkg/gnolang/nodes_span.go index 3222f499c8f..97d5f6af5a6 100644 --- a/gnovm/pkg/gnolang/nodes_span.go +++ b/gnovm/pkg/gnolang/nodes_span.go @@ -114,6 +114,8 @@ func (s Span) GetSpan() Span { // If you need to update the span/pos/location of a node it should be re-parsed // from an updated AST. This is important because location is used as identity. // Anyone with a node can still mutate these fields directly; the method guides. +// If you need to override the span (e.g. constructing a Location by mutating +// a copy) then call SetSpanOverride() instead of directly assigning to .Span. func (s1 *Span) SetSpan(s2 Span) { if !s1.IsZero() && (*s1 != s2) { panic(".Span can ony be set once. s1:" + s1.String() + " s2:" + s2.String()) @@ -121,6 +123,11 @@ func (s1 *Span) SetSpan(s2 Span) { *s1 = s2 } +// See documentation for SetSpan(). +func (s1 *Span) SetSpanOverride(s2 Span) { + *s1 = s2 +} + // Overridden by Attributes.String(). func (s Span) String() string { if s.Pos.Line == s.End.Line { @@ -136,12 +143,6 @@ func (s Span) String() string { } } -// XXX delete this after fixing all tests. -func (s Span) StringXXX() string { - return fmt.Sprintf("%d:%d", - s.Pos.Line, s.Pos.Column) -} - // Overridden by Attributes.IsZero(). // NOTE: DO NOT CHANGE. func (s Span) IsZero() bool { @@ -221,15 +222,6 @@ type Location struct { Span } -// XXX Delete this after fixing all tests. -func (loc Location) StringXXX() string { - return fmt.Sprintf("%s/%s:%s", - loc.PkgPath, - loc.File, - loc.Span.StringXXX(), - ) -} - // Overridden by Attributes.String(). func (loc Location) String() string { return fmt.Sprintf("%s/%s:%s", diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cdba832fa3f..70966c056c8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -408,9 +408,8 @@ func doRecover(stack []BlockNode, n Node) { // before re-throwing the error, append location information to message. last := stack[len(stack)-1] loc := last.GetLocation() - if nline := n.GetLine(); nline > 0 { - loc.Line = nline - loc.Column = n.GetColumn() + if !n.GetSpan().IsZero() { + loc.SetSpanOverride(n.GetSpan()) } var err error @@ -418,7 +417,7 @@ func doRecover(stack []BlockNode, n Node) { if ok { err = errors.Wrap(rerr, loc.String()) } else { - err = fmt.Errorf("%s: %v", loc.StringXXX(), r) // XXX revert to String(). + err = fmt.Errorf("%s: %v", loc.String(), r) } // Re-throw the error after wrapping it with the preprocessing stack information. diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index e8cd0d9379e..4fe09b48beb 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -395,7 +395,6 @@ func checkValDefineMismatch(n Node) { if numNames > numValues { panic(fmt.Sprintf("missing init expr for %s", valueDecl.NameExprs[numValues].String())) } - panic(fmt.Sprintf("extra init expr %s", values[numNames].String())) } diff --git a/gnovm/pkg/repl/repl_test.go b/gnovm/pkg/repl/repl_test.go index 58b75188dde..5f5162881d3 100644 --- a/gnovm/pkg/repl/repl_test.go +++ b/gnovm/pkg/repl/repl_test.go @@ -69,7 +69,7 @@ var fixtures = []struct { CodeSteps: []step{ { Line: "importasdasd", - Error: "test/test1.gno:7:2: name importasdasd not declared", + Error: "test/test1.gno:7:2-14: name importasdasd not declared", }, { Line: "var a := 1", diff --git a/gnovm/tests/files/access1.gno b/gnovm/tests/files/access1.gno index f6df8007a66..e3ffc5ca296 100644 --- a/gnovm/tests/files/access1.gno +++ b/gnovm/tests/files/access1.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/access1.gno:8:10: cannot access gno.land/p/demo/testutils.testVar2 from main +// main/access1.gno:8:10-28: cannot access gno.land/p/demo/testutils.testVar2 from main // TypeCheckError: // main/access1.gno:8:20: name testVar2 not exported by package testutils diff --git a/gnovm/tests/files/access4.gno b/gnovm/tests/files/access4.gno index bf328793835..64916b1d412 100644 --- a/gnovm/tests/files/access4.gno +++ b/gnovm/tests/files/access4.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/access4.gno:9:10: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main +// main/access4.gno:9:10-24: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main // TypeCheckError: // main/access4.gno:9:12: x.privateField undefined (cannot refer to unexported field privateField) diff --git a/gnovm/tests/files/access6.gno b/gnovm/tests/files/access6.gno index 07d816dcd13..679972120bb 100644 --- a/gnovm/tests/files/access6.gno +++ b/gnovm/tests/files/access6.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/access6.gno:15:2: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) +// main/access6.gno:15:2-36: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) // TypeCheckError: // main/access6.gno:15:34: cannot use x (variable of struct type mystruct) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: mystruct does not implement testutils.PrivateInterface (unexported method privateMethod) diff --git a/gnovm/tests/files/access7.gno b/gnovm/tests/files/access7.gno index e8cfb32a4e8..74f3dfbb92f 100644 --- a/gnovm/tests/files/access7.gno +++ b/gnovm/tests/files/access7.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/access7.gno:19:2: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) +// main/access7.gno:19:2-36: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface (missing method privateMethod) // TypeCheckError: // main/access7.gno:19:34: cannot use x (variable of interface type PrivateInterface2) as testutils.PrivateInterface value in argument to testutils.PrintPrivateInterface: PrivateInterface2 does not implement testutils.PrivateInterface (missing method privateMethod) diff --git a/gnovm/tests/files/add3.gno b/gnovm/tests/files/add3.gno index 9dd7aeef4be..20509f25dcd 100644 --- a/gnovm/tests/files/add3.gno +++ b/gnovm/tests/files/add3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/add3.gno:5:7: invalid operation: a + (const (undefined)) (mismatched types int and untyped nil) +// main/add3.gno:5:7-14: invalid operation: a + (const (undefined)) (mismatched types int and untyped nil) // TypeCheckError: // main/add3.gno:5:7: invalid operation: a + nil (mismatched types int and untyped nil); main/add3.gno:5:2: declared and not used: i diff --git a/gnovm/tests/files/addressable_7a_err.gno b/gnovm/tests/files/addressable_7a_err.gno index fe3f15e45c1..811e1a07daf 100644 --- a/gnovm/tests/files/addressable_7a_err.gno +++ b/gnovm/tests/files/addressable_7a_err.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/addressable_7a_err.gno:8:2: getTypeOf() only supports *CallExpr with 1 result, got ([]int,[]string) +// main/addressable_7a_err.gno:8:2-12: getTypeOf() only supports *CallExpr with 1 result, got ([]int,[]string) // TypeCheckError: // main/addressable_7a_err.gno:8:7: multiple-value foo() (value of type ([]int, []string)) in single-value context diff --git a/gnovm/tests/files/addressable_7b_err.gno b/gnovm/tests/files/addressable_7b_err.gno index 71beaa89a95..7655aecc595 100644 --- a/gnovm/tests/files/addressable_7b_err.gno +++ b/gnovm/tests/files/addressable_7b_err.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/addressable_7b_err.gno:4:2: RHS should not be &((const (9 int))) when len(Lhs) > len(Rhs) +// main/addressable_7b_err.gno:4:2-16: RHS should not be &((const (9 int))) when len(Lhs) > len(Rhs) // TypeCheckError: // main/addressable_7b_err.gno:4:10: invalid operation: cannot take address of int(9) (constant 9 of type int) diff --git a/gnovm/tests/files/assign11.gno b/gnovm/tests/files/assign11.gno index 97e809dde8e..a3f5b82c850 100644 --- a/gnovm/tests/files/assign11.gno +++ b/gnovm/tests/files/assign11.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/assign11.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign11.gno:6:2-31: assignment mismatch: 3 variables but fmt.Println returns 2 values // TypeCheckError: // main/assign11.gno:6:12: assignment mismatch: 3 variables but fmt.Println returns 2 values diff --git a/gnovm/tests/files/assign12.gno b/gnovm/tests/files/assign12.gno index ad9e9b4e10e..6b510dc8ab2 100644 --- a/gnovm/tests/files/assign12.gno +++ b/gnovm/tests/files/assign12.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/assign12.gno:6:2: assignment mismatch: 3 variables but fmt.Println returns 2 values +// main/assign12.gno:6:2-32: assignment mismatch: 3 variables but fmt.Println returns 2 values // TypeCheckError: // main/assign12.gno:6:13: assignment mismatch: 3 variables but fmt.Println returns 2 values diff --git a/gnovm/tests/files/assign22.gno b/gnovm/tests/files/assign22.gno index 3322ae4a7b7..8e214e3e73c 100644 --- a/gnovm/tests/files/assign22.gno +++ b/gnovm/tests/files/assign22.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign22.gno:7:2: assignment operator <<= requires only one expression on lhs and rhs +// main/assign22.gno:7:2-18: assignment operator <<= requires only one expression on lhs and rhs // TypeCheckError: // main/assign22.gno:7:8: assignment operation <<= requires single-valued expressions; main/assign22.gno:4:2: declared and not used: m diff --git a/gnovm/tests/files/assign23.gno b/gnovm/tests/files/assign23.gno index 5f4b8db941f..7c1a3f8e0dd 100644 --- a/gnovm/tests/files/assign23.gno +++ b/gnovm/tests/files/assign23.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign23.gno:7:2: assignment operator += requires only one expression on lhs and rhs +// main/assign23.gno:7:2-17: assignment operator += requires only one expression on lhs and rhs // TypeCheckError: // main/assign23.gno:7:8: assignment operation += requires single-valued expressions; main/assign23.gno:4:2: declared and not used: m diff --git a/gnovm/tests/files/assign24.gno b/gnovm/tests/files/assign24.gno index 660a0907e49..4a61095be61 100644 --- a/gnovm/tests/files/assign24.gno +++ b/gnovm/tests/files/assign24.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign24.gno:4:2: assignment mismatch: 2 variable(s) but 1 value(s) +// main/assign24.gno:4:2-11: assignment mismatch: 2 variable(s) but 1 value(s) // TypeCheckError: // main/assign24.gno:4:10: assignment mismatch: 2 variables but 1 value; main/assign24.gno:4:2: declared and not used: a; main/assign24.gno:4:5: declared and not used: b diff --git a/gnovm/tests/files/assign25.gno b/gnovm/tests/files/assign25.gno index f83b897e7bd..011c84375db 100644 --- a/gnovm/tests/files/assign25.gno +++ b/gnovm/tests/files/assign25.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign25.gno:8:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/assign25.gno:8:2-21: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: // main/assign25.gno:8:13: assignment mismatch: 3 variables but 2 values diff --git a/gnovm/tests/files/assign25b.gno b/gnovm/tests/files/assign25b.gno index bb07ab8dcd6..567949d2951 100644 --- a/gnovm/tests/files/assign25b.gno +++ b/gnovm/tests/files/assign25b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign25b.gno:8:2: assignment mismatch: 3 variable(s) but 4 value(s) +// main/assign25b.gno:8:2-27: assignment mismatch: 3 variable(s) but 4 value(s) // TypeCheckError: // main/assign25b.gno:8:13: assignment mismatch: 3 variables but 4 values diff --git a/gnovm/tests/files/assign25c.gno b/gnovm/tests/files/assign25c.gno index cee43530eb8..ba41e534aeb 100644 --- a/gnovm/tests/files/assign25c.gno +++ b/gnovm/tests/files/assign25c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/assign25c.gno:10:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/assign25c.gno:10:2-19: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: // main/assign25c.gno:10:13: assignment mismatch: 3 variables but 2 values diff --git a/gnovm/tests/files/assign25d.gno b/gnovm/tests/files/assign25d.gno index aa9550d803a..73e25b50026 100644 --- a/gnovm/tests/files/assign25d.gno +++ b/gnovm/tests/files/assign25d.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/assign25d.gno:10:2: assignment mismatch: 3 variable(s) but 4 value(s) +// main/assign25d.gno:10:2-25: assignment mismatch: 3 variable(s) but 4 value(s) // TypeCheckError: // main/assign25d.gno:10:13: assignment mismatch: 3 variables but 4 values diff --git a/gnovm/tests/files/assign26.gno b/gnovm/tests/files/assign26.gno index 4b97268984a..993f7914e41 100644 --- a/gnovm/tests/files/assign26.gno +++ b/gnovm/tests/files/assign26.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/assign26.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) +// main/assign26.gno:5:2-20: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: // main/assign26.gno:5:13: assignment mismatch: 3 variables but 1 value; main/assign26.gno:5:2: declared and not used: a; main/assign26.gno:5:5: declared and not used: b; main/assign26.gno:5:8: declared and not used: c diff --git a/gnovm/tests/files/assign27.gno b/gnovm/tests/files/assign27.gno index 3cc39a12354..bdd17cb7b5f 100644 --- a/gnovm/tests/files/assign27.gno +++ b/gnovm/tests/files/assign27.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/assign27.gno:5:2: assignment mismatch: 3 variable(s) but 1 value(s) +// main/assign27.gno:5:2-17: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: // main/assign27.gno:5:13: assignment mismatch: 3 variables but 1 value; main/assign27.gno:5:2: declared and not used: a; main/assign27.gno:5:5: declared and not used: b; main/assign27.gno:5:8: declared and not used: c diff --git a/gnovm/tests/files/assign28.gno b/gnovm/tests/files/assign28.gno index 784a19a8934..1c292af338c 100644 --- a/gnovm/tests/files/assign28.gno +++ b/gnovm/tests/files/assign28.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/assign28.gno:6:2: assignment mismatch: 2 variable(s) but 3 value(s) +// main/assign28.gno:6:2-17: assignment mismatch: 2 variable(s) but 3 value(s) // TypeCheckError: // main/assign28.gno:6:10: assignment mismatch: 2 variables but 3 values diff --git a/gnovm/tests/files/assign29.gno b/gnovm/tests/files/assign29.gno index ce43f0dcb89..2045750791a 100644 --- a/gnovm/tests/files/assign29.gno +++ b/gnovm/tests/files/assign29.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign29.gno:4:2: struct{} (type) is not an expression +// main/assign29.gno:4:2-15: struct{} (type) is not an expression // TypeCheckError: // main/assign29.gno:4:7: struct{} (type) is not an expression; main/assign29.gno:4:2: declared and not used: t diff --git a/gnovm/tests/files/assign30.gno b/gnovm/tests/files/assign30.gno index 98c13be352a..a4c40205021 100644 --- a/gnovm/tests/files/assign30.gno +++ b/gnovm/tests/files/assign30.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign30.gno:4:2: *struct{} (type) is not an expression +// main/assign30.gno:4:2-16: *struct{} (type) is not an expression // TypeCheckError: // main/assign30.gno:4:7: *struct{} (type) is not an expression; main/assign30.gno:4:2: declared and not used: t diff --git a/gnovm/tests/files/assign31.gno b/gnovm/tests/files/assign31.gno index 874cada7440..a9fc7332144 100644 --- a/gnovm/tests/files/assign31.gno +++ b/gnovm/tests/files/assign31.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/assign31.gno:4:2: use of untyped nil in assignment +// main/assign31.gno:4:2-10: use of untyped nil in assignment // TypeCheckError: // main/assign31.gno:4:7: use of untyped nil in assignment diff --git a/gnovm/tests/files/assign33.gno b/gnovm/tests/files/assign33.gno index 214a8a9ab07..a73de8c10cf 100644 --- a/gnovm/tests/files/assign33.gno +++ b/gnovm/tests/files/assign33.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/assign33.gno:8:6: cannot use foo() (value of type bool) as int value in assignment +// main/assign33.gno:8:6-22: cannot use foo() (value of type bool) as int value in assignment // TypeCheckError: // main/assign33.gno:8:17: cannot use foo() (value of type bool) as int value in assignment diff --git a/gnovm/tests/files/assign35.gno b/gnovm/tests/files/assign35.gno index 97f425548ab..6c25e774b6e 100644 --- a/gnovm/tests/files/assign35.gno +++ b/gnovm/tests/files/assign35.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign35.gno:8:2: multiple-value foo (value of type [int bool]) in single-value context +// main/assign35.gno:8:2-18: multiple-value foo (value of type [int bool]) in single-value context // TypeCheckError: // main/assign35.gno:8:13: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/assign37.gno b/gnovm/tests/files/assign37.gno index 9a06ce31837..f7ceb3f1e1c 100644 --- a/gnovm/tests/files/assign37.gno +++ b/gnovm/tests/files/assign37.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/assign37.gno:6:2: f (no value) used as value +// main/assign37.gno:6:2-10: f (no value) used as value // TypeCheckError: // main/assign37.gno:6:7: f() (no value) used as value; main/assign37.gno:6:2: declared and not used: a diff --git a/gnovm/tests/files/assign37b.gno b/gnovm/tests/files/assign37b.gno index a6b12b7a0e7..7508ea65c52 100644 --- a/gnovm/tests/files/assign37b.gno +++ b/gnovm/tests/files/assign37b.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign37b.gno:8:2: f (no value) used as value +// main/assign37b.gno:8:2-18: f (no value) used as value // TypeCheckError: // main/assign37b.gno:8:10: f() (no value) used as value; main/assign37b.gno:8:15: f() (no value) used as value; main/assign37b.gno:8:2: declared and not used: a; main/assign37b.gno:8:5: declared and not used: b; main/assign37b.gno:3:8: "fmt" imported and not used diff --git a/gnovm/tests/files/assign38.gno b/gnovm/tests/files/assign38.gno index 399e4c1dded..b19a367161c 100644 --- a/gnovm/tests/files/assign38.gno +++ b/gnovm/tests/files/assign38.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/assign38.gno:5:2: cannot use nil as int value in assignment +// main/assign38.gno:5:2-9: cannot use nil as int value in assignment // TypeCheckError: // main/assign38.gno:5:6: cannot use nil as int value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno index 8b51f51d0c0..e6d78418338 100644 --- a/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/named_unnamed_type2_filetest.gno:11:7: cannot use int as int64 +// main/named_unnamed_type2_filetest.gno:11:7-32: cannot use int as int64 // TypeCheckError: // main/named_unnamed_type2_filetest.gno:11:23: cannot use nlist (variable of slice type nat) as []int64 value in argument to append 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 d5a40c0b5b1..4653b6eaa11 100644 --- a/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/declaredType6_filetest.gno:15:2: cannot use []main.c as []main.word +// main/declaredType6_filetest.gno:15:2-14: cannot use []main.c as []main.word // TypeCheckError: // main/declaredType6_filetest.gno:15:8: cannot use []c{…} (value of type []c) as nat value in assignment 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 1cb60a74c8a..c31ccccaa09 100644 --- a/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/declaredType6b_filetest.gno:15:2: cannot use []uint as []main.word +// main/declaredType6b_filetest.gno:15:2-17: cannot use []uint as []main.word // TypeCheckError: // main/declaredType6b_filetest.gno:15:8: cannot use []uint{…} (value of type []uint) as nat value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno index 471f7a04ad8..05b29671e0c 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/assgin_two_filetest.gno:11:2: cannot use main.nat2 as main.nat without explicit conversion +// main/assgin_two_filetest.gno:11:2-7: cannot use main.nat2 as main.nat without explicit conversion // TypeCheckError: // main/assgin_two_filetest.gno:11:6: cannot use b (variable of slice type nat2) as nat value in assignment diff --git a/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno index 8000770d7f0..03cee01a97f 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/return_interface1_filetest.gno:10:2: cannot use interface {} as uint +// main/return_interface1_filetest.gno:10:2-10: cannot use interface {} as uint // TypeCheckError: // main/return_interface1_filetest.gno:10:6: cannot use x1() (value of interface type any) as uint value in assignment: need type assertion; main/return_interface1_filetest.gno:9:6: declared and not used: a diff --git a/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno index 085d0188563..bd4eb6e480a 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/return_interface_filetest.gno:13:2: cannot use interface {} as []int +// main/return_interface_filetest.gno:13:2-9: cannot use interface {} as []int // TypeCheckError: // main/return_interface_filetest.gno:13:6: cannot use x() (value of interface type any) as nat value in assignment: need type assertion diff --git a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno index 0e259226166..eec32dd2b7c 100644 --- a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/unnamedtype0b_filetest.gno:11:2: cannot use []main.word as []int +// main/unnamedtype0b_filetest.gno:11:2-7: cannot use []main.word as []int // TypeCheckError: // main/unnamedtype0b_filetest.gno:11:6: cannot use b (variable of type []word) as nat value in assignment diff --git a/gnovm/tests/files/blankidentifier0.gno b/gnovm/tests/files/blankidentifier0.gno index a82f18df127..02971c881dd 100644 --- a/gnovm/tests/files/blankidentifier0.gno +++ b/gnovm/tests/files/blankidentifier0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/blankidentifier0.gno:4:6: cannot use _ as value or type +// main/blankidentifier0.gno:4:6-7: cannot use _ as value or type // TypeCheckError: // main/blankidentifier0.gno:4:6: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier2.gno b/gnovm/tests/files/blankidentifier2.gno index 97614beae62..d579d7c0096 100644 --- a/gnovm/tests/files/blankidentifier2.gno +++ b/gnovm/tests/files/blankidentifier2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/blankidentifier2.gno:4:6: cannot use _ as value or type +// main/blankidentifier2.gno:4:6-9: cannot use _ as value or type // TypeCheckError: // main/blankidentifier2.gno:4:8: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier3.gno b/gnovm/tests/files/blankidentifier3.gno index d7ef4378ee2..36afc0a5c99 100644 --- a/gnovm/tests/files/blankidentifier3.gno +++ b/gnovm/tests/files/blankidentifier3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/blankidentifier3.gno:3:6: cannot use _ as value or type +// main/blankidentifier3.gno:3:6-9: cannot use _ as value or type // TypeCheckError: // main/blankidentifier3.gno:3:8: cannot use _ as value or type diff --git a/gnovm/tests/files/blankidentifier6.gno b/gnovm/tests/files/blankidentifier6.gno index 90954b4c4e7..4f865f865a7 100644 --- a/gnovm/tests/files/blankidentifier6.gno +++ b/gnovm/tests/files/blankidentifier6.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/blankidentifier6.gno:18:13: cannot use _ as value or type +// main/blankidentifier6.gno:18:13-14: cannot use _ as value or type // TypeCheckError: // main/blankidentifier6.gno:18:13: cannot use _ as value or type diff --git a/gnovm/tests/files/block2.gno b/gnovm/tests/files/block2.gno index 065524e1fcd..6cbe7902d1e 100644 --- a/gnovm/tests/files/block2.gno +++ b/gnovm/tests/files/block2.gno @@ -547,4 +547,4 @@ func main() { } // Error: -// main/block2.gno:419:129: exceeded maximum VPBlock depth (127) +// main/block2.gno:419:129-130: exceeded maximum VPBlock depth (127) diff --git a/gnovm/tests/files/bltn0.gno b/gnovm/tests/files/bltn0.gno index 5a34457690d..cfce6e60a65 100644 --- a/gnovm/tests/files/bltn0.gno +++ b/gnovm/tests/files/bltn0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/bltn0.gno:4:7: use of builtin println not in function call +// main/bltn0.gno:4:7-14: use of builtin println not in function call // TypeCheckError: // main/bltn0.gno:4:7: println (built-in) must be called diff --git a/gnovm/tests/files/bool6.gno b/gnovm/tests/files/bool6.gno index eb367481eee..9d9913ffa76 100644 --- a/gnovm/tests/files/bool6.gno +++ b/gnovm/tests/files/bool6.gno @@ -9,7 +9,7 @@ func X() string { } // Error: -// main/bool6.gno:8:9: operator || not defined on: StringKind +// main/bool6.gno:8:9-27: operator || not defined on: StringKind // TypeCheckError: // main/bool6.gno:8:9: invalid operation: operator || not defined on "hello" (untyped string constant) diff --git a/gnovm/tests/files/break0.gno b/gnovm/tests/files/break0.gno index 3e6207286b4..8eddc7af32d 100644 --- a/gnovm/tests/files/break0.gno +++ b/gnovm/tests/files/break0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/break0.gno:4:2: break statement out of place +// main/break0.gno:4:2-7: break statement out of place // TypeCheckError: // main/break0.gno:4:2: break not in for, switch, or select statement diff --git a/gnovm/tests/files/circular_constant.gno b/gnovm/tests/files/circular_constant.gno index b73196ec3fb..f5aa5b98cbb 100644 --- a/gnovm/tests/files/circular_constant.gno +++ b/gnovm/tests/files/circular_constant.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/circular_constant.gno:3:7: invalid recursive value: A -> B -> A +// main/circular_constant.gno:3:7-12: invalid recursive value: A -> B -> A // TypeCheckError: // main/circular_constant.gno:3:7: initialization cycle for A; main/circular_constant.gno:3:7: A refers to B; main/circular_constant.gno:4:7: B refers to A diff --git a/gnovm/tests/files/const23.gno b/gnovm/tests/files/const23.gno index 0d641f2c0db..fa796fa325a 100644 --- a/gnovm/tests/files/const23.gno +++ b/gnovm/tests/files/const23.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/const23.gno:6:8: invalid constant type []string +// main/const23.gno:6:8-31: invalid constant type []string // TypeCheckError: // main/const23.gno:6:10: invalid constant type []string diff --git a/gnovm/tests/files/const25.gno b/gnovm/tests/files/const25.gno index 629a7d829c2..f1049e188f8 100644 --- a/gnovm/tests/files/const25.gno +++ b/gnovm/tests/files/const25.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant +// main/const25.gno:6:8-25: [](const-type string){(const ("1" string))} (variable of type []string) is not constant // TypeCheckError: // main/const25.gno:6:12: []string{…} (value of type []string) is not constant diff --git a/gnovm/tests/files/const26.gno b/gnovm/tests/files/const26.gno index c454d89b912..03c9a2346ff 100644 --- a/gnovm/tests/files/const26.gno +++ b/gnovm/tests/files/const26.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/const26.gno:10:8: v() (value of type string) is not constant +// main/const26.gno:10:8-15: v() (value of type string) is not constant // TypeCheckError: // main/const26.gno:10:12: v() (value of type string) is not constant diff --git a/gnovm/tests/files/const27.gno b/gnovm/tests/files/const27.gno index cb3ef82e39b..8c18f3c4dbe 100644 --- a/gnovm/tests/files/const27.gno +++ b/gnovm/tests/files/const27.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/const27.gno:11:8: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant +// main/const27.gno:11:8-23: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant // TypeCheckError: // main/const27.gno:11:11: missing init expr for ok; main/const27.gno:11:16: i.(int) (comma, ok expression of type int) is not constant diff --git a/gnovm/tests/files/const28.gno b/gnovm/tests/files/const28.gno index bc32782aa75..2f534c38844 100644 --- a/gnovm/tests/files/const28.gno +++ b/gnovm/tests/files/const28.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const28.gno:7:8: s[(const (0 int))] (variable of type string) is not constant +// main/const28.gno:7:8-20: s[(const (0 int))] (variable of type string) is not constant // TypeCheckError: // main/const28.gno:7:11: missing init expr for ok; main/const28.gno:7:16: s[0] (variable of type string) is not constant diff --git a/gnovm/tests/files/const29.gno b/gnovm/tests/files/const29.gno index b35cd6708f4..26bc887f5c2 100644 --- a/gnovm/tests/files/const29.gno +++ b/gnovm/tests/files/const29.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const29.gno:7:8: s (variable of type string) is not constant +// main/const29.gno:7:8-13: s (variable of type string) is not constant // TypeCheckError: // main/const29.gno:7:12: s (variable of type string) is not constant diff --git a/gnovm/tests/files/const30.gno b/gnovm/tests/files/const30.gno index cbc15c1804e..1d1a70c3f59 100644 --- a/gnovm/tests/files/const30.gno +++ b/gnovm/tests/files/const30.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/const30.gno:10:8: v (no value) used as value +// main/const30.gno:10:8-15: v (no value) used as value // TypeCheckError: // main/const30.gno:10:12: v() (no value) used as value diff --git a/gnovm/tests/files/const31.gno b/gnovm/tests/files/const31.gno index 8e40aaa52e5..f5478106682 100644 --- a/gnovm/tests/files/const31.gno +++ b/gnovm/tests/files/const31.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/const31.gno:10:8: (const (v func() (string, string)))() (variable of type (string,string)) is not constant +// main/const31.gno:10:8-18: (const (v func() (string, string)))() (variable of type (string,string)) is not constant // TypeCheckError: // main/const31.gno:10:11: missing init expr for v; main/const31.gno:10:15: multiple-value v() (value of type (string, string)) in single-value context diff --git a/gnovm/tests/files/const32.gno b/gnovm/tests/files/const32.gno index 8d0cf2aae00..92b83a43691 100644 --- a/gnovm/tests/files/const32.gno +++ b/gnovm/tests/files/const32.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant +// main/const32.gno:6:8-35: [](const-type string){} (variable of type []string) is not constant // TypeCheckError: // main/const32.gno:6:12: 1 + 2 + len([]string{}) (value of type int) is not constant diff --git a/gnovm/tests/files/const33.gno b/gnovm/tests/files/const33.gno index 0492bcb2204..9ccf0c175db 100644 --- a/gnovm/tests/files/const33.gno +++ b/gnovm/tests/files/const33.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/const33.gno:6:7: x (variable of type int) is not constant +// main/const33.gno:6:7-17: x (variable of type int) is not constant // TypeCheckError: // main/const33.gno:6:11: x == y (untyped bool value) is not constant diff --git a/gnovm/tests/files/const34.gno b/gnovm/tests/files/const34.gno index f9043d43b3a..def38d3e379 100644 --- a/gnovm/tests/files/const34.gno +++ b/gnovm/tests/files/const34.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const34.gno:3:7: func func(){ println("hey") } (variable of type func()) is not constant +// main/const34.gno:3:7-36: func func(){ println("hey") } (variable of type func()) is not constant // TypeCheckError: // main/const34.gno:3:11: (func() literal) (value of type func()) is not constant diff --git a/gnovm/tests/files/const35.gno b/gnovm/tests/files/const35.gno index 7b063636f4c..49918e883a2 100644 --- a/gnovm/tests/files/const35.gno +++ b/gnovm/tests/files/const35.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const35.gno:5:7: x (variable of type int) is not constant +// main/const35.gno:5:7-21: x (variable of type int) is not constant // TypeCheckError: // main/const35.gno:5:12: +(1 << x) (untyped int value) is not constant diff --git a/gnovm/tests/files/const36.gno b/gnovm/tests/files/const36.gno index 5c7857ffc9f..952cb41ceef 100644 --- a/gnovm/tests/files/const36.gno +++ b/gnovm/tests/files/const36.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/const36.gno:9:8: s.x (variable of type int) is not constant +// main/const36.gno:9:8-15: s.x (variable of type int) is not constant // TypeCheckError: // main/const36.gno:9:12: s.x (variable of type int) is not constant diff --git a/gnovm/tests/files/const37_native.gno b/gnovm/tests/files/const37_native.gno index ad35bb5cd28..e1bcedadd58 100644 --- a/gnovm/tests/files/const37_native.gno +++ b/gnovm/tests/files/const37_native.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const37_native.gno:6:8: time.UTC (variable of type *time.Location) is not constant +// main/const37_native.gno:6:8-20: time.UTC (variable of type *time.Location) is not constant // TypeCheckError: // main/const37_native.gno:6:12: time.UTC (variable of type *time.Location) is not constant diff --git a/gnovm/tests/files/const37_stdlibs.gno b/gnovm/tests/files/const37_stdlibs.gno index 45452f44e3e..c82ed97a36d 100644 --- a/gnovm/tests/files/const37_stdlibs.gno +++ b/gnovm/tests/files/const37_stdlibs.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const37_stdlibs.gno:6:8: time.UTC (variable of type *time.Location) is not constant +// main/const37_stdlibs.gno:6:8-20: time.UTC (variable of type *time.Location) is not constant // TypeCheckError: // main/const37_stdlibs.gno:6:12: time.UTC (variable of type *time.Location) is not constant diff --git a/gnovm/tests/files/const38.gno b/gnovm/tests/files/const38.gno index bcb96a42f26..a37460025db 100644 --- a/gnovm/tests/files/const38.gno +++ b/gnovm/tests/files/const38.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/const38.gno:7:8: v.Denom (variable of type string) is not constant +// main/const38.gno:7:8-19: v.Denom (variable of type string) is not constant // TypeCheckError: // main/const38.gno:7:12: v.Denom (variable of type string) is not constant diff --git a/gnovm/tests/files/const39.gno b/gnovm/tests/files/const39.gno index 737e14e7c50..0954c5292c6 100644 --- a/gnovm/tests/files/const39.gno +++ b/gnovm/tests/files/const39.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/const39.gno:10:8: typeval{main.T}.Mv (variable of type func(main.T, int) int) is not constant +// main/const39.gno:10:8-16: typeval{main.T}.Mv (variable of type func(main.T, int) int) is not constant // TypeCheckError: // main/const39.gno:10:12: T.Mv (value of type func(tv T, a int) int) is not constant diff --git a/gnovm/tests/files/const40.gno b/gnovm/tests/files/const40.gno index 2edf7e8879f..5bf5340dbf8 100644 --- a/gnovm/tests/files/const40.gno +++ b/gnovm/tests/files/const40.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/const40.gno:4:8: [(const (0 int))](const-type string){} (variable of type [0]string) is not constant +// main/const40.gno:4:8-23: [(const (0 int))](const-type string){} (variable of type [0]string) is not constant // TypeCheckError: // main/const40.gno:4:12: [0]string{} (value of type [0]string) is not constant diff --git a/gnovm/tests/files/const41.gno b/gnovm/tests/files/const41.gno index 36876159da3..fcfae2925fd 100644 --- a/gnovm/tests/files/const41.gno +++ b/gnovm/tests/files/const41.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/const41.gno:4:8: invalid constant type [0]string +// main/const41.gno:4:8-33: invalid constant type [0]string // TypeCheckError: // main/const41.gno:4:10: invalid constant type [0]string diff --git a/gnovm/tests/files/const43.gno b/gnovm/tests/files/const43.gno index 99e3bf223c9..1ae6efc68df 100644 --- a/gnovm/tests/files/const43.gno +++ b/gnovm/tests/files/const43.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const43.gno:6:8: a (variable of type [2]int) is not constant +// main/const43.gno:6:8-13: a (variable of type [2]int) is not constant // TypeCheckError: // main/const43.gno:6:12: a (variable of type [2]int) is not constant diff --git a/gnovm/tests/files/const44.gno b/gnovm/tests/files/const44.gno index 3c85abd8280..93de134b32b 100644 --- a/gnovm/tests/files/const44.gno +++ b/gnovm/tests/files/const44.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/const44.gno:3:7: (const (undefined)) (variable of type interface {}) is not constant +// main/const44.gno:3:7-19: (const (undefined)) (variable of type interface {}) is not constant // TypeCheckError: // main/const44.gno:3:11: any(nil) (value of interface type any) is not constant diff --git a/gnovm/tests/files/const45_b.gno b/gnovm/tests/files/const45_b.gno index df5f48bc664..b8eb7c9cd8a 100644 --- a/gnovm/tests/files/const45_b.gno +++ b/gnovm/tests/files/const45_b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/const45_b.gno:7:7: typeval{main.MyStruct}{arr: [](const-type int){(const (1 int)), (const (2 int))}}.arr (variable of type []int) is not constant +// main/const45_b.gno:7:7-46: typeval{main.MyStruct}{arr: [](const-type int){(const (1 int)), (const (2 int))}}.arr (variable of type []int) is not constant // TypeCheckError: // main/const45_b.gno:7:11: len(MyStruct{…}.arr) (value of type int) is not constant diff --git a/gnovm/tests/files/const48.gno b/gnovm/tests/files/const48.gno index 5f8610bd5f3..4e56a5bf7f8 100644 --- a/gnovm/tests/files/const48.gno +++ b/gnovm/tests/files/const48.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/const48.gno:4:8: map[(const-type string)] [](const-type int){(const ("arr" string)): (const-type []int){(const (1 int)), (const (2 int))}} (variable of type map[string][]int) is not constant +// main/const48.gno:4:8-48: map[(const-type string)] [](const-type int){(const ("arr" string)): (const-type []int){(const (1 int)), (const (2 int))}} (variable of type map[string][]int) is not constant // TypeCheckError: // main/const48.gno:4:12: len(map[string][]int{…}) (value of type int) is not constant diff --git a/gnovm/tests/files/const50.gno b/gnovm/tests/files/const50.gno index dd51c516ed9..c513947c11f 100644 --- a/gnovm/tests/files/const50.gno +++ b/gnovm/tests/files/const50.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const50.gno:5:7: x (variable of type string) is not constant +// main/const50.gno:5:7-17: x (variable of type string) is not constant // TypeCheckError: // main/const50.gno:5:11: len(x) (value of type int) is not constant diff --git a/gnovm/tests/files/const55.gno b/gnovm/tests/files/const55.gno index 7805139b662..e9b9b213d0a 100644 --- a/gnovm/tests/files/const55.gno +++ b/gnovm/tests/files/const55.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/const55.gno:5:2: assignment mismatch: 1 variable(s) but 2 value(s) +// main/const55.gno:5:2-3: assignment mismatch: 1 variable(s) but 2 value(s) // TypeCheckError: // main/const55.gno:5:2: extra init expr at main/const55.gno:4:2 diff --git a/gnovm/tests/files/const55a.gno b/gnovm/tests/files/const55a.gno index 05147685bac..2521778880d 100644 --- a/gnovm/tests/files/const55a.gno +++ b/gnovm/tests/files/const55a.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/const55a.gno:5:2: assignment mismatch: 3 variable(s) but 2 value(s) +// main/const55a.gno:5:2-9: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: // main/const55a.gno:5:8: missing init expr for l diff --git a/gnovm/tests/files/const60.gno b/gnovm/tests/files/const60.gno index 5d8abef4217..e847aa070f7 100644 --- a/gnovm/tests/files/const60.gno +++ b/gnovm/tests/files/const60.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const60.gno:4:6: bigint underflows target kind +// main/const60.gno:4:6-14: bigint underflows target kind // TypeCheckError: // main/const60.gno:4:11: constant -2 overflows uint diff --git a/gnovm/tests/files/const61.gno b/gnovm/tests/files/const61.gno index e478bcfd7f2..c6edc23137f 100644 --- a/gnovm/tests/files/const61.gno +++ b/gnovm/tests/files/const61.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/const61.gno:4:6: bigint underflows target kind +// main/const61.gno:4:6-15: bigint underflows target kind // TypeCheckError: // main/const61.gno:4:12: constant -1 overflows uint8 diff --git a/gnovm/tests/files/const9.gno b/gnovm/tests/files/const9.gno index c57d738d757..e60f02b2e5e 100644 --- a/gnovm/tests/files/const9.gno +++ b/gnovm/tests/files/const9.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/const9.gno:5:2: invalid recursive value: b -> c -> d -> e -> b +// main/const9.gno:5:2-11: invalid recursive value: b -> c -> d -> e -> b // TypeCheckError: // main/const9.gno:6:2: initialization cycle for c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b; main/const9.gno:5:2: b refers to c; main/const9.gno:5:2: initialization cycle for b; main/const9.gno:5:2: b refers to c; main/const9.gno:6:2: c refers to d; main/const9.gno:7:2: d refers to e; main/const9.gno:8:2: e refers to b diff --git a/gnovm/tests/files/cont3.gno b/gnovm/tests/files/cont3.gno index e064c78030d..ff1934e6479 100644 --- a/gnovm/tests/files/cont3.gno +++ b/gnovm/tests/files/cont3.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/cont3.gno:4:2: continue statement out of place +// main/cont3.gno:4:2-10: continue statement out of place // TypeCheckError: // main/cont3.gno:4:2: continue not in for statement diff --git a/gnovm/tests/files/convert4.gno b/gnovm/tests/files/convert4.gno index 3c4e6800d69..7734b642f4e 100644 --- a/gnovm/tests/files/convert4.gno +++ b/gnovm/tests/files/convert4.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/convert4.gno:4:10: cannot convert (const (undefined)) to IntKind +// main/convert4.gno:4:10-18: cannot convert (const (undefined)) to IntKind // TypeCheckError: // main/convert4.gno:4:14: cannot convert nil to type int diff --git a/gnovm/tests/files/convert5.gno b/gnovm/tests/files/convert5.gno index 77a1398b17b..71af90e1d23 100644 --- a/gnovm/tests/files/convert5.gno +++ b/gnovm/tests/files/convert5.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/convert5.gno:3:1: cannot convert (const (undefined)) to IntKind +// main/convert5.gno:3:1-7:2: cannot convert (const (undefined)) to IntKind // TypeCheckError: // main/convert5.gno:5:22: cannot use nil as int value in argument to append; main/convert5.gno:5:27: cannot use nil as int value in argument to append diff --git a/gnovm/tests/files/convert6.gno b/gnovm/tests/files/convert6.gno index cc926ae01ee..df3dcb286c1 100644 --- a/gnovm/tests/files/convert6.gno +++ b/gnovm/tests/files/convert6.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6.gno:5:10: cannot convert constant of type IntKind to UintKind +// main/convert6.gno:5:10-17: cannot convert constant of type IntKind to UintKind // TypeCheckError: // main/convert6.gno:5:15: constant -1 overflows uint diff --git a/gnovm/tests/files/convert6a.gno b/gnovm/tests/files/convert6a.gno index 5fa4d162170..ac60fdaa3f6 100644 --- a/gnovm/tests/files/convert6a.gno +++ b/gnovm/tests/files/convert6a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6a.gno:5:10: cannot convert constant of type IntKind to Uint8Kind +// main/convert6a.gno:5:10-18: cannot convert constant of type IntKind to Uint8Kind // TypeCheckError: // main/convert6a.gno:5:16: constant -1 overflows uint8 diff --git a/gnovm/tests/files/convert6b.gno b/gnovm/tests/files/convert6b.gno index f59e4fd8032..04e672215a1 100644 --- a/gnovm/tests/files/convert6b.gno +++ b/gnovm/tests/files/convert6b.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6b.gno:5:10: cannot convert constant of type IntKind to Uint16Kind +// main/convert6b.gno:5:10-19: cannot convert constant of type IntKind to Uint16Kind // TypeCheckError: // main/convert6b.gno:5:17: constant -1 overflows uint16 diff --git a/gnovm/tests/files/convert6c.gno b/gnovm/tests/files/convert6c.gno index 2b66f53fefa..9701854dce9 100644 --- a/gnovm/tests/files/convert6c.gno +++ b/gnovm/tests/files/convert6c.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6c.gno:5:10: cannot convert constant of type IntKind to Uint32Kind +// main/convert6c.gno:5:10-19: cannot convert constant of type IntKind to Uint32Kind // TypeCheckError: // main/convert6c.gno:5:17: constant -1 overflows uint32 diff --git a/gnovm/tests/files/convert6d.gno b/gnovm/tests/files/convert6d.gno index 4637193198f..2514263a254 100644 --- a/gnovm/tests/files/convert6d.gno +++ b/gnovm/tests/files/convert6d.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6d.gno:5:10: cannot convert constant of type IntKind to Uint64Kind +// main/convert6d.gno:5:10-19: cannot convert constant of type IntKind to Uint64Kind // TypeCheckError: // main/convert6d.gno:5:17: constant -1 overflows uint64 diff --git a/gnovm/tests/files/convert6e.gno b/gnovm/tests/files/convert6e.gno index ef448c95742..98ae7667bf4 100644 --- a/gnovm/tests/files/convert6e.gno +++ b/gnovm/tests/files/convert6e.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert6e.gno:5:10: cannot convert constant of type Float32Kind to Int32Kind +// main/convert6e.gno:5:10-18: cannot convert constant of type Float32Kind to Int32Kind // TypeCheckError: // main/convert6e.gno:5:16: cannot convert a (constant 1.5 of type float32) to type int32 diff --git a/gnovm/tests/files/convert7.gno b/gnovm/tests/files/convert7.gno index 1fe04e43343..d3086fd003a 100644 --- a/gnovm/tests/files/convert7.gno +++ b/gnovm/tests/files/convert7.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/convert7.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type +// main/convert7.gno:4:10-20: cannot convert (const (1.5 bigdec)) to integer type // TypeCheckError: // main/convert7.gno:4:16: cannot convert 1.5 (untyped float constant) to type int32 diff --git a/gnovm/tests/files/convert7a.gno b/gnovm/tests/files/convert7a.gno index 5de35bda8fa..27b04ff83f8 100644 --- a/gnovm/tests/files/convert7a.gno +++ b/gnovm/tests/files/convert7a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/convert7a.gno:5:10: cannot convert constant of type Float64Kind to Int64Kind +// main/convert7a.gno:5:10-18: cannot convert constant of type Float64Kind to Int64Kind // TypeCheckError: // main/convert7a.gno:5:16: cannot convert a (constant 1.5 of type float64) to type int64 diff --git a/gnovm/tests/files/convert7b.gno b/gnovm/tests/files/convert7b.gno index 8546bf8f70d..bb92984a470 100644 --- a/gnovm/tests/files/convert7b.gno +++ b/gnovm/tests/files/convert7b.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/convert7b.gno:4:10: cannot convert (const (1.5 bigdec)) to integer type +// main/convert7b.gno:4:10-20: cannot convert (const (1.5 bigdec)) to integer type // TypeCheckError: // main/convert7b.gno:4:16: cannot convert 1.5 (untyped float constant) to type int64 diff --git a/gnovm/tests/files/float0.gno b/gnovm/tests/files/float0.gno index 84bf17a878d..d7b48546ed6 100644 --- a/gnovm/tests/files/float0.gno +++ b/gnovm/tests/files/float0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/float0.gno:4:7: cannot convert (const (1.2 bigdec)) to integer type +// main/float0.gno:4:7-15: cannot convert (const (1.2 bigdec)) to integer type // TypeCheckError: // main/float0.gno:4:11: cannot convert 1.2 (untyped float constant) to type int diff --git a/gnovm/tests/files/for21.gno b/gnovm/tests/files/for21.gno index fd4a9b4afa2..4d55daf6187 100644 --- a/gnovm/tests/files/for21.gno +++ b/gnovm/tests/files/for21.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/for21.gno:7:17: continue statement out of place +// main/for21.gno:7:17-25: continue statement out of place // TypeCheckError: // main/for21.gno:7:17: continue not in for statement diff --git a/gnovm/tests/files/for22.gno b/gnovm/tests/files/for22.gno index aef1942c18e..f86cffd274f 100644 --- a/gnovm/tests/files/for22.gno +++ b/gnovm/tests/files/for22.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/for22.gno:7:17: fallthrough statement out of place +// main/for22.gno:7:17-28: fallthrough statement out of place // TypeCheckError: // main/for22.gno:7:17: fallthrough statement out of place diff --git a/gnovm/tests/files/for23.gno b/gnovm/tests/files/for23.gno index 76a489a6f2e..5cf96206096 100644 --- a/gnovm/tests/files/for23.gno +++ b/gnovm/tests/files/for23.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/for23.gno:7:17: break statement out of place +// main/for23.gno:7:17-22: break statement out of place // TypeCheckError: // main/for23.gno:7:17: break not in for, switch, or select statement diff --git a/gnovm/tests/files/for24.gno b/gnovm/tests/files/for24.gno index 3945675bb7c..ed79cfba322 100644 --- a/gnovm/tests/files/for24.gno +++ b/gnovm/tests/files/for24.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/for24.gno:8:21: break statement out of place +// main/for24.gno:8:21-26: break statement out of place // TypeCheckError: // main/for24.gno:8:21: break not in for, switch, or select statement diff --git a/gnovm/tests/files/for7.gno b/gnovm/tests/files/for7.gno index ea98a27aa76..0cfde742ddd 100644 --- a/gnovm/tests/files/for7.gno +++ b/gnovm/tests/files/for7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/for7.gno:4:2: expected typed bool kind, but got IntKind +// main/for7.gno:4:2-5:3: expected typed bool kind, but got IntKind // TypeCheckError: // main/for7.gno:4:14: non-boolean condition in for statement diff --git a/gnovm/tests/files/fun21.gno b/gnovm/tests/files/fun21.gno index aa601eb1b26..58441462acd 100644 --- a/gnovm/tests/files/fun21.gno +++ b/gnovm/tests/files/fun21.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/fun21.gno:4:2: expected 1 return values; got 0 +// main/fun21.gno:4:2-8: expected 1 return values; got 0 // TypeCheckError: // main/fun21.gno:4:2: not enough return values diff --git a/gnovm/tests/files/fun22.gno b/gnovm/tests/files/fun22.gno index 694d2d2ebbf..a154d7e6244 100644 --- a/gnovm/tests/files/fun22.gno +++ b/gnovm/tests/files/fun22.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/fun22.gno:6:2: wrong argument count in call to time.Date; want 8 got 0 +// main/fun22.gno:6:2-13: wrong argument count in call to time.Date; want 8 got 0 // TypeCheckError: // main/fun22.gno:6:12: not enough arguments in call to time.Date diff --git a/gnovm/tests/files/fun23.gno b/gnovm/tests/files/fun23.gno index 666864ce375..199ba1856c9 100644 --- a/gnovm/tests/files/fun23.gno +++ b/gnovm/tests/files/fun23.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/fun23.gno:3:17: expected 0 return values; got 1 +// main/fun23.gno:3:17-25: expected 0 return values; got 1 // TypeCheckError: // main/fun23.gno:3:24: too many return values diff --git a/gnovm/tests/files/fun24.gno b/gnovm/tests/files/fun24.gno index 3a94719b5e2..ae9a40c29a4 100644 --- a/gnovm/tests/files/fun24.gno +++ b/gnovm/tests/files/fun24.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/fun24.gno:3:28: cannot use untyped string as IntKind +// main/fun24.gno:3:28-43: cannot use untyped string as IntKind // TypeCheckError: // main/fun24.gno:3:38: cannot use "foo" (untyped string constant) as int value in return statement diff --git a/gnovm/tests/files/fun25.gno b/gnovm/tests/files/fun25.gno index e5e150b3828..cb40440a859 100644 --- a/gnovm/tests/files/fun25.gno +++ b/gnovm/tests/files/fun25.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/fun25.gno:3:35: cannot use string as int +// main/fun25.gno:3:35-46: cannot use string as int // TypeCheckError: // main/fun25.gno:3:42: cannot use x (variable of type string) as int value in return statement diff --git a/gnovm/tests/files/fun27.gno b/gnovm/tests/files/fun27.gno index b5c8fd22e33..22f1f4f738b 100644 --- a/gnovm/tests/files/fun27.gno +++ b/gnovm/tests/files/fun27.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/fun27.gno:8:2: bigint does not implement main.Foo (missing method foo) +// main/fun27.gno:8:2-10: bigint does not implement main.Foo (missing method foo) // TypeCheckError: // main/fun27.gno:8:9: cannot use 1 (constant of type int) as Foo value in return statement: int does not implement Foo (missing method foo) diff --git a/gnovm/tests/files/fun28.gno b/gnovm/tests/files/fun28.gno index 54745b56aac..1bb1ace7397 100644 --- a/gnovm/tests/files/fun28.gno +++ b/gnovm/tests/files/fun28.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/fun28.gno:6:2: cannot use nil as int value in argument to f +// main/fun28.gno:6:2-8: cannot use nil as int value in argument to f // TypeCheckError: // main/fun28.gno:6:4: cannot use nil as int value in argument to f diff --git a/gnovm/tests/files/govdao/realm_govdao.gno b/gnovm/tests/files/govdao/realm_govdao.gno index 984fbdb1be1..ba1716db17f 100644 --- a/gnovm/tests/files/govdao/realm_govdao.gno +++ b/gnovm/tests/files/govdao/realm_govdao.gno @@ -72,4 +72,4 @@ func Render() { } // Error: -// gno.land/r/gov/dao/v3/memberstore/memberstore.gno:125:2: builtin identifiers cannot be shadowed: realm +// gno.land/r/gov/dao/v3/memberstore/memberstore.gno:125:2-7: builtin identifiers cannot be shadowed: realm diff --git a/gnovm/tests/files/if2.gno b/gnovm/tests/files/if2.gno index a312d04ba1c..74a4a4a9a8d 100644 --- a/gnovm/tests/files/if2.gno +++ b/gnovm/tests/files/if2.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/if2.gno:7:2: expected typed bool kind, but got IntKind +// main/if2.gno:7:2-9:3: expected typed bool kind, but got IntKind // TypeCheckError: // main/if2.gno:7:5: non-boolean condition in if statement diff --git a/gnovm/tests/files/import10.gno b/gnovm/tests/files/import10.gno index bfd425009b9..c23253674dd 100644 --- a/gnovm/tests/files/import10.gno +++ b/gnovm/tests/files/import10.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/import10.gno:7:10: package fmt cannot only be referred to in a selector expression +// main/import10.gno:7:10-13: package fmt cannot only be referred to in a selector expression // TypeCheckError: // main/import10.gno:7:10: use of package fmt not in selector diff --git a/gnovm/tests/files/import11.gno b/gnovm/tests/files/import11.gno index dd93d3443c9..5beaffd9c77 100644 --- a/gnovm/tests/files/import11.gno +++ b/gnovm/tests/files/import11.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// gno.land/p/demo/bar/import11.gno:5:2: pure package path "gno.land/p/demo/bar" cannot import realm path "gno.land/r/demo/tests" +// gno.land/p/demo/bar/import11.gno:5:2-25: pure package path "gno.land/p/demo/bar" cannot import realm path "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/import12.gno b/gnovm/tests/files/import12.gno index 43f7d3b3a15..9426eb4c500 100644 --- a/gnovm/tests/files/import12.gno +++ b/gnovm/tests/files/import12.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/import12.gno:6:2: cannot import stdlib internal/ package outside of standard library +// gno.land/p/demo/import12.gno:6:2-20: cannot import stdlib internal/ package outside of standard library diff --git a/gnovm/tests/files/import13.gno b/gnovm/tests/files/import13.gno index 91ce598e4cc..64ccdb5db91 100644 --- a/gnovm/tests/files/import13.gno +++ b/gnovm/tests/files/import13.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/import13.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" +// gno.land/p/demo/import13.gno:6:2-48: internal/ packages can only be imported by packages rooted at the parent of "internal" diff --git a/gnovm/tests/files/import13b.gno b/gnovm/tests/files/import13b.gno index 3a77017d254..ab5ea4e1fed 100644 --- a/gnovm/tests/files/import13b.gno +++ b/gnovm/tests/files/import13b.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// gno.land/p/demo/import13b.gno:6:2: internal/ packages can only be imported by packages rooted at the parent of "internal" +// gno.land/p/demo/import13b.gno:6:2-45: internal/ packages can only be imported by packages rooted at the parent of "internal" diff --git a/gnovm/tests/files/import6.gno b/gnovm/tests/files/import6.gno index f3cd9930eb5..c0a8c54a5cc 100644 --- a/gnovm/tests/files/import6.gno +++ b/gnovm/tests/files/import6.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// github.com/gnolang/gno/_test/c2/c2.gno:3:8: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) +// github.com/gnolang/gno/_test/c2/c2.gno:3:8-41: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) diff --git a/gnovm/tests/files/init1.gno b/gnovm/tests/files/init1.gno index 3ef5dfd87b0..5d25a3d97a3 100644 --- a/gnovm/tests/files/init1.gno +++ b/gnovm/tests/files/init1.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/init1.gno:8:2: name init not declared +// main/init1.gno:8:2-6: name init not declared // TypeCheckError: // main/init1.gno:8:2: undefined: init diff --git a/gnovm/tests/files/interface47.gno b/gnovm/tests/files/interface47.gno index a89bf4c38fc..bd7c23ee19b 100644 --- a/gnovm/tests/files/interface47.gno +++ b/gnovm/tests/files/interface47.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/interface47.gno:13:10: main.Runner does not implement main.Swimmer (missing method Swim) +// main/interface47.gno:13:10-20: main.Runner does not implement main.Swimmer (missing method Swim) // TypeCheckError: // main/interface47.gno:13:18: cannot convert a (variable of interface type Runner) to type Swimmer: Runner does not implement Swimmer (missing method Swim) diff --git a/gnovm/tests/files/invalid_labels0.gno b/gnovm/tests/files/invalid_labels0.gno index f7e78aaa93e..0fe9d109719 100644 --- a/gnovm/tests/files/invalid_labels0.gno +++ b/gnovm/tests/files/invalid_labels0.gno @@ -11,4 +11,4 @@ FirstLoop: } // Error: -// main/invalid_labels0.gno:9:3: cannot find branch label "FirstLoop" +// main/invalid_labels0.gno:9:3-18: cannot find branch label "FirstLoop" diff --git a/gnovm/tests/files/invalid_labels2.gno b/gnovm/tests/files/invalid_labels2.gno index ca6062f2f01..4b515428573 100644 --- a/gnovm/tests/files/invalid_labels2.gno +++ b/gnovm/tests/files/invalid_labels2.gno @@ -12,7 +12,7 @@ FirstLoop: } // Error: -// main/invalid_labels2.gno:7:3: cannot find branch label "FirstLoop" +// main/invalid_labels2.gno:7:3-21: cannot find branch label "FirstLoop" // TypeCheckError: // main/invalid_labels2.gno:7:12: invalid continue label FirstLoop; main/invalid_labels2.gno:9:1: label FirstLoop declared and not used diff --git a/gnovm/tests/files/native0.gno b/gnovm/tests/files/native0.gno index 3b422473cfe..c62dc541531 100644 --- a/gnovm/tests/files/native0.gno +++ b/gnovm/tests/files/native0.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/native0.gno:3:1: function invalidNative does not have a body but is not natively defined (did you build after pulling from the repository?) +// main/native0.gno:3:1-28: function invalidNative does not have a body but is not natively defined (did you build after pulling from the repository?) diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index 8321bc6bc24..a3211b4b5d2 100644 --- a/gnovm/tests/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/op7.gno:11:5: operator > not defined on: InterfaceKind +// main/op7.gno:11:5-19: operator > not defined on: InterfaceKind // TypeCheckError: // main/op7.gno:11:5: invalid operation: err > invalidT (operator > not defined on interface) diff --git a/gnovm/tests/files/overflow10.gno b/gnovm/tests/files/overflow10.gno index 061feb1130c..8543b81b38b 100644 --- a/gnovm/tests/files/overflow10.gno +++ b/gnovm/tests/files/overflow10.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow10.gno:3:1: constant overflows +// main/overflow10.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow10.gno:4:13: int64(1) << 65 (constant 36893488147419103232 of type int64) overflows int64 diff --git a/gnovm/tests/files/overflow11.gno b/gnovm/tests/files/overflow11.gno index 93bd4fc7c75..cfcfb764b37 100644 --- a/gnovm/tests/files/overflow11.gno +++ b/gnovm/tests/files/overflow11.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow11.gno:3:1: constant overflows +// main/overflow11.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow11.gno:4:13: uint8(1) << 8 (constant 256 of type uint8) overflows uint8 diff --git a/gnovm/tests/files/overflow12.gno b/gnovm/tests/files/overflow12.gno index 4c19c35903b..cc7f477be44 100644 --- a/gnovm/tests/files/overflow12.gno +++ b/gnovm/tests/files/overflow12.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow12.gno:3:1: constant overflows +// main/overflow12.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow12.gno:4:16: uint16(1) << 16 (constant 65536 of type uint16) overflows uint16 diff --git a/gnovm/tests/files/overflow13.gno b/gnovm/tests/files/overflow13.gno index 07f6c166f7b..296dff22295 100644 --- a/gnovm/tests/files/overflow13.gno +++ b/gnovm/tests/files/overflow13.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow13.gno:3:1: constant overflows +// main/overflow13.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow13.gno:4:13: uint32(1) << 33 (constant 8589934592 of type uint32) overflows uint32 diff --git a/gnovm/tests/files/overflow14.gno b/gnovm/tests/files/overflow14.gno index 62324d1802a..357005e24cd 100644 --- a/gnovm/tests/files/overflow14.gno +++ b/gnovm/tests/files/overflow14.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow14.gno:3:1: constant overflows +// main/overflow14.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow14.gno:4:16: uint64(1) << 65 (constant 36893488147419103232 of type uint64) overflows uint64 diff --git a/gnovm/tests/files/overflow16.gno b/gnovm/tests/files/overflow16.gno index 16c5abe5365..0b3e9031e9d 100644 --- a/gnovm/tests/files/overflow16.gno +++ b/gnovm/tests/files/overflow16.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/overflow16.gno:5:2: bigint overflows target kind +// main/overflow16.gno:5:2-13: bigint overflows target kind // TypeCheckError: // main/overflow16.gno:5:10: cannot use c1 (untyped int constant 340282366920938463463374607431768211456) as int value in argument to built-in println (overflows) diff --git a/gnovm/tests/files/overflow6.gno b/gnovm/tests/files/overflow6.gno index e8fcc3aa425..537c7d9e99e 100644 --- a/gnovm/tests/files/overflow6.gno +++ b/gnovm/tests/files/overflow6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow6.gno:3:1: constant overflows +// main/overflow6.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow6.gno:4:12: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 diff --git a/gnovm/tests/files/overflow7.gno b/gnovm/tests/files/overflow7.gno index b8547729e49..ade9c5ba411 100644 --- a/gnovm/tests/files/overflow7.gno +++ b/gnovm/tests/files/overflow7.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow7.gno:3:1: constant overflows +// main/overflow7.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow7.gno:4:13: int8(1) << 8 (constant 256 of type int8) overflows int8 diff --git a/gnovm/tests/files/overflow8.gno b/gnovm/tests/files/overflow8.gno index 0f039d2fce6..40132a73542 100644 --- a/gnovm/tests/files/overflow8.gno +++ b/gnovm/tests/files/overflow8.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow8.gno:3:1: constant overflows +// main/overflow8.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow8.gno:4:13: int16(1) << 16 (constant 65536 of type int16) overflows int16 diff --git a/gnovm/tests/files/overflow9.gno b/gnovm/tests/files/overflow9.gno index 1e7c892893b..d28ecc7d188 100644 --- a/gnovm/tests/files/overflow9.gno +++ b/gnovm/tests/files/overflow9.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/overflow9.gno:3:1: constant overflows +// main/overflow9.gno:3:1-5:2: constant overflows // TypeCheckError: // main/overflow9.gno:4:13: int32(1) << 33 (constant 8589934592 of type int32) overflows int32 diff --git a/gnovm/tests/files/pkgname1.gno b/gnovm/tests/files/pkgname1.gno index e7d1edd367d..9f849b03b16 100644 --- a/gnovm/tests/files/pkgname1.gno +++ b/gnovm/tests/files/pkgname1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/pkgname1.gno:5:2: package name for "github.com/gnolang/gno/_test/bar" ("quux") doesn't match its expected identifier "bar"; the import declaration must specify an identifier +// main/pkgname1.gno:5:2-36: package name for "github.com/gnolang/gno/_test/bar" ("quux") doesn't match its expected identifier "bar"; the import declaration must specify an identifier // TypeCheckError: // main/pkgname1.gno:9:19: undefined: bar; main/pkgname1.gno:5:2: "github.com/gnolang/gno/_test/bar" imported as quux and not used diff --git a/gnovm/tests/files/ptr10.gno b/gnovm/tests/files/ptr10.gno index 27b58f898b2..feb8dbd46c4 100644 --- a/gnovm/tests/files/ptr10.gno +++ b/gnovm/tests/files/ptr10.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/ptr10.gno:4:10: invalid operation: cannot indirect nil +// main/ptr10.gno:4:10-14: invalid operation: cannot indirect nil // TypeCheckError: // main/ptr10.gno:4:11: invalid operation: cannot indirect nil diff --git a/gnovm/tests/files/ptr9.gno b/gnovm/tests/files/ptr9.gno index 2998a1c1481..fd4f6d09f32 100644 --- a/gnovm/tests/files/ptr9.gno +++ b/gnovm/tests/files/ptr9.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/ptr9.gno:5:10: invalid operation: cannot indirect v (variable of type int) +// main/ptr9.gno:5:10-12: invalid operation: cannot indirect v (variable of type int) // TypeCheckError: // main/ptr9.gno:5:11: invalid operation: cannot indirect v (variable of type int) diff --git a/gnovm/tests/files/range8.gno b/gnovm/tests/files/range8.gno index 12dfbe0cd03..7762d097181 100644 --- a/gnovm/tests/files/range8.gno +++ b/gnovm/tests/files/range8.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/range8.gno:4:2: cannot range over nil +// main/range8.gno:4:2-6:3: cannot range over nil // TypeCheckError: // main/range8.gno:4:20: cannot range over nil diff --git a/gnovm/tests/files/recursive1.gno b/gnovm/tests/files/recursive1.gno index 4fd477b11a3..840a3ca2214 100644 --- a/gnovm/tests/files/recursive1.gno +++ b/gnovm/tests/files/recursive1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/recursive1.gno:3:6: invalid recursive type: S -> S +// main/recursive1.gno:3:6-5:2: invalid recursive type: S -> S // TypeCheckError: // main/recursive1.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1c.gno b/gnovm/tests/files/recursive1c.gno index 16ad2402dfc..e939bbaf4a5 100644 --- a/gnovm/tests/files/recursive1c.gno +++ b/gnovm/tests/files/recursive1c.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/recursive1c.gno:5:6: invalid recursive type: S -> S +// main/recursive1c.gno:5:6-7:2: invalid recursive type: S -> S // TypeCheckError: // main/recursive1c.gno:5:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1d.gno b/gnovm/tests/files/recursive1d.gno index f9cab595095..7fe0b7618bb 100644 --- a/gnovm/tests/files/recursive1d.gno +++ b/gnovm/tests/files/recursive1d.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/recursive1d.gno:5:6: invalid recursive type: S -> S +// main/recursive1d.gno:5:6-7:2: invalid recursive type: S -> S // TypeCheckError: // main/recursive1d.gno:5:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive1f.gno b/gnovm/tests/files/recursive1f.gno index 65fb88644e3..3ed5e1ecaf0 100644 --- a/gnovm/tests/files/recursive1f.gno +++ b/gnovm/tests/files/recursive1f.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/recursive1f.gno:4:7: invalid recursive type: S -> S +// main/recursive1f.gno:4:7-6:3: invalid recursive type: S -> S // TypeCheckError: // main/recursive1f.gno:4:7: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive2.gno b/gnovm/tests/files/recursive2.gno index 3967e6f90f6..82b52ce7467 100644 --- a/gnovm/tests/files/recursive2.gno +++ b/gnovm/tests/files/recursive2.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/recursive2.gno:3:6: invalid recursive type: A -> B -> C -> A +// main/recursive2.gno:3:6-5:2: invalid recursive type: A -> B -> C -> A // TypeCheckError: // main/recursive2.gno:3:6: invalid recursive type A; main/recursive2.gno:3:6: A refers to B; main/recursive2.gno:7:6: B refers to C; main/recursive2.gno:11:6: C refers to A diff --git a/gnovm/tests/files/recursive2c.gno b/gnovm/tests/files/recursive2c.gno index 1c7ec961c01..e041faf6095 100644 --- a/gnovm/tests/files/recursive2c.gno +++ b/gnovm/tests/files/recursive2c.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/recursive2c.gno:4:7: name B not defined in fileset with files [recursive2c.gno] +// main/recursive2c.gno:4:7-6:3: name B not defined in fileset with files [recursive2c.gno] // TypeCheckError: // main/recursive2c.gno:5:5: undefined: B; main/recursive2c.gno:9:5: undefined: C diff --git a/gnovm/tests/files/recursive4a.gno b/gnovm/tests/files/recursive4a.gno index ef5323faa3c..c1714480fde 100644 --- a/gnovm/tests/files/recursive4a.gno +++ b/gnovm/tests/files/recursive4a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/recursive4a.gno:3:6: invalid recursive type: time -> time +// main/recursive4a.gno:3:6-24: invalid recursive type: time -> time // TypeCheckError: // main/recursive4a.gno:3:6: invalid recursive type: time refers to itself diff --git a/gnovm/tests/files/recursive5.gno b/gnovm/tests/files/recursive5.gno index 468fa4627b8..c1887d5bfa2 100644 --- a/gnovm/tests/files/recursive5.gno +++ b/gnovm/tests/files/recursive5.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/recursive5.gno:3:6: invalid recursive type: S -> S +// main/recursive5.gno:3:6-5:2: invalid recursive type: S -> S // TypeCheckError: // main/recursive5.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive6a.gno b/gnovm/tests/files/recursive6a.gno index 5ecff3d6bc3..e6faa8962f3 100644 --- a/gnovm/tests/files/recursive6a.gno +++ b/gnovm/tests/files/recursive6a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/recursive6a.gno:3:6: invalid recursive type: SelfReferencing -> SelfReferencing +// main/recursive6a.gno:3:6-5:2: invalid recursive type: SelfReferencing -> SelfReferencing // TypeCheckError: // main/recursive6a.gno:3:6: invalid recursive type: SelfReferencing refers to itself diff --git a/gnovm/tests/files/recursive7a.gno b/gnovm/tests/files/recursive7a.gno index d09c956bc28..dae6611ed3f 100644 --- a/gnovm/tests/files/recursive7a.gno +++ b/gnovm/tests/files/recursive7a.gno @@ -5,7 +5,7 @@ type S [2]S func main() {} // Error: -// main/recursive7a.gno:3:6: invalid recursive type: S -> S +// main/recursive7a.gno:3:6-12: invalid recursive type: S -> S // TypeCheckError: // main/recursive7a.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/recursive8.gno b/gnovm/tests/files/recursive8.gno index e719a09adb9..d3bad756fe7 100644 --- a/gnovm/tests/files/recursive8.gno +++ b/gnovm/tests/files/recursive8.gno @@ -5,7 +5,7 @@ type Int Int func main() {} // Error: -// main/recursive8.gno:3:6: invalid recursive type: Int -> Int +// main/recursive8.gno:3:6-13: invalid recursive type: Int -> Int // TypeCheckError: // main/recursive8.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9.gno b/gnovm/tests/files/recursive9.gno index f89f7eef0b6..969edf09dc2 100644 --- a/gnovm/tests/files/recursive9.gno +++ b/gnovm/tests/files/recursive9.gno @@ -5,7 +5,7 @@ type Int = Int func main() {} // Error: -// main/recursive9.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9.gno:3:6-15: invalid recursive type: Int -> Int // TypeCheckError: // main/recursive9.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9a.gno b/gnovm/tests/files/recursive9a.gno index 0fd1ad1580b..db0c2c9e60a 100644 --- a/gnovm/tests/files/recursive9a.gno +++ b/gnovm/tests/files/recursive9a.gno @@ -5,7 +5,7 @@ type Int = *Int func main() {} // Error: -// main/recursive9a.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9a.gno:3:6-16: invalid recursive type: Int -> Int // TypeCheckError: // main/recursive9a.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9b.gno b/gnovm/tests/files/recursive9b.gno index f5aedc9475c..48f5bd4d479 100644 --- a/gnovm/tests/files/recursive9b.gno +++ b/gnovm/tests/files/recursive9b.gno @@ -5,7 +5,7 @@ type Int = func() Int func main() {} // Error: -// main/recursive9b.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9b.gno:3:6-22: invalid recursive type: Int -> Int // TypeCheckError: // main/recursive9b.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9c.gno b/gnovm/tests/files/recursive9c.gno index dc2cec3d403..121f48bf844 100644 --- a/gnovm/tests/files/recursive9c.gno +++ b/gnovm/tests/files/recursive9c.gno @@ -5,7 +5,7 @@ type Int = []Int func main() {} // Error: -// main/recursive9c.gno:3:6: invalid recursive type: Int -> Int +// main/recursive9c.gno:3:6-17: invalid recursive type: Int -> Int // TypeCheckError: // main/recursive9c.gno:3:6: invalid recursive type: Int refers to itself diff --git a/gnovm/tests/files/recursive9d.gno b/gnovm/tests/files/recursive9d.gno index f0823322c15..66dc8152f61 100644 --- a/gnovm/tests/files/recursive9d.gno +++ b/gnovm/tests/files/recursive9d.gno @@ -7,7 +7,7 @@ type S = struct { func main() {} // Error: -// main/recursive9d.gno:3:6: invalid recursive type: S -> S +// main/recursive9d.gno:3:6-5:2: invalid recursive type: S -> S // TypeCheckError: // main/recursive9d.gno:3:6: invalid recursive type: S refers to itself diff --git a/gnovm/tests/files/redeclaration9.gno b/gnovm/tests/files/redeclaration9.gno index 5927f0cdb71..a7cfb42f0fc 100644 --- a/gnovm/tests/files/redeclaration9.gno +++ b/gnovm/tests/files/redeclaration9.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/redeclaration9.gno:7:1: redeclaration of method a.method +// main/redeclaration9.gno:7:1-37: redeclaration of method a.method // TypeCheckError: // main/redeclaration9.gno:7:12: method a.method already declared at main/redeclaration9.gno:5:12 diff --git a/gnovm/tests/files/slice3.gno b/gnovm/tests/files/slice3.gno index b390d295b10..88a52a1d229 100644 --- a/gnovm/tests/files/slice3.gno +++ b/gnovm/tests/files/slice3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/slice3.gno:4:7: cannot use nil as string value in array, slice literal or map literal +// main/slice3.gno:4:7-20: cannot use nil as string value in array, slice literal or map literal // TypeCheckError: // main/slice3.gno:4:16: cannot use nil as string value in array or slice literal diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files/switch13.gno index 5a34da281c1..10c07027637 100644 --- a/gnovm/tests/files/switch13.gno +++ b/gnovm/tests/files/switch13.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/switch13.gno:9:2: i is not a type +// main/switch13.gno:9:2-10:24: i is not a type // TypeCheckError: // main/switch13.gno:9:7: i is not a type diff --git a/gnovm/tests/files/switch19.gno b/gnovm/tests/files/switch19.gno index 92d39635e08..bee52b331b8 100644 --- a/gnovm/tests/files/switch19.gno +++ b/gnovm/tests/files/switch19.gno @@ -48,7 +48,7 @@ func main() { } // Error: -// main/switch19.gno:34:2: duplicate type main.Bir in type switch +// main/switch19.gno:34:2-41:3: duplicate type main.Bir in type switch // TypeCheckError: // main/switch19.gno:37:7: duplicate case Bir in type switch; main/switch19.gno:35:12: previous case diff --git a/gnovm/tests/files/switch8.gno b/gnovm/tests/files/switch8.gno index f300e69d211..42cbbb89e58 100644 --- a/gnovm/tests/files/switch8.gno +++ b/gnovm/tests/files/switch8.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/switch8.gno:5:2: fallthrough statement out of place +// main/switch8.gno:5:2-13: fallthrough statement out of place // TypeCheckError: // main/switch8.gno:5:2: fallthrough statement out of place diff --git a/gnovm/tests/files/switch8b.gno b/gnovm/tests/files/switch8b.gno index eef0e2a9268..9023975847a 100644 --- a/gnovm/tests/files/switch8b.gno +++ b/gnovm/tests/files/switch8b.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/switch8b.gno:10:3: cannot fallthrough final case in switch +// main/switch8b.gno:10:3-14: cannot fallthrough final case in switch // TypeCheckError: // main/switch8b.gno:10:3: cannot fallthrough final case in switch diff --git a/gnovm/tests/files/switch8c.gno b/gnovm/tests/files/switch8c.gno index 519e5d71649..f5592242d92 100644 --- a/gnovm/tests/files/switch8c.gno +++ b/gnovm/tests/files/switch8c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/switch8c.gno:7:3: fallthrough statement out of place +// main/switch8c.gno:7:3-14: fallthrough statement out of place // TypeCheckError: // main/switch8c.gno:7:3: fallthrough statement out of place diff --git a/gnovm/tests/files/switch9.gno b/gnovm/tests/files/switch9.gno index cfb568dd985..e211bcdaa1e 100644 --- a/gnovm/tests/files/switch9.gno +++ b/gnovm/tests/files/switch9.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/switch9.gno:9:3: cannot fallthrough in type switch +// main/switch9.gno:9:3-14: cannot fallthrough in type switch // TypeCheckError: // main/switch9.gno:9:3: cannot fallthrough in type switch diff --git a/gnovm/tests/files/type30.gno b/gnovm/tests/files/type30.gno index a71520f953b..29aaf179cf5 100644 --- a/gnovm/tests/files/type30.gno +++ b/gnovm/tests/files/type30.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/type30.gno:15:10: cannot use main.String as string without explicit conversion +// main/type30.gno:15:10-21: cannot use main.String as string without explicit conversion // TypeCheckError: // main/type30.gno:15:19: cannot use y (variable of string type String) as string value in argument to equal diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index bb272a2d25e..8fab8a10c8b 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/type31.gno:8:10: invalid operation: x + y (mismatched types string and main.String) +// main/type31.gno:8:10-15: invalid operation: x + y (mismatched types string and main.String) // TypeCheckError: // main/type31.gno:8:10: invalid operation: x + y (mismatched types string and String) diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index 463dab56f98..20cbd7edc38 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/type32.gno:9:11: invalid operation: a + (const (":" string)) + b (mismatched types string and main.S) +// main/type32.gno:9:11-22: invalid operation: a + (const (":" string)) + b (mismatched types string and main.S) // TypeCheckError: // main/type32.gno:9:11: invalid operation: a + ":" + b (mismatched types string and S) diff --git a/gnovm/tests/files/type37.gno b/gnovm/tests/files/type37.gno index de6c2f60f36..801ad404943 100644 --- a/gnovm/tests/files/type37.gno +++ b/gnovm/tests/files/type37.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/type37.gno:8:1: invalid receiver type main.Arr (base type is pointer type) +// main/type37.gno:8:1-10:2: invalid receiver type main.Arr (base type is pointer type) // TypeCheckError: // main/type37.gno:8:9: invalid receiver type Arr (pointer or interface type); main/type37.gno:14:9: Arr(a).Add undefined (type Arr has no field or method Add) diff --git a/gnovm/tests/files/type37b.gno b/gnovm/tests/files/type37b.gno index 17211a96352..4141b2c0240 100644 --- a/gnovm/tests/files/type37b.gno +++ b/gnovm/tests/files/type37b.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/type37b.gno:7:1: invalid receiver type **main.Integer (base type is pointer type) +// main/type37b.gno:7:1-9:2: invalid receiver type **main.Integer (base type is pointer type) // TypeCheckError: // main/type37b.gno:7:10: invalid receiver type **Integer; main/type37b.gno:16:4: b.Add undefined (type **Integer has no field or method Add) diff --git a/gnovm/tests/files/type37d.gno b/gnovm/tests/files/type37d.gno index 3650cdc8c4e..e5d16e66255 100644 --- a/gnovm/tests/files/type37d.gno +++ b/gnovm/tests/files/type37d.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/type37d.gno:7:1: invalid receiver type main.IntPtr (base type is pointer type) +// main/type37d.gno:7:1-9:2: invalid receiver type main.IntPtr (base type is pointer type) // TypeCheckError: // main/type37d.gno:7:9: invalid receiver type IntPtr (pointer or interface type); main/type37d.gno:12:13: ip.Int undefined (type IntPtr has no field or method Int) diff --git a/gnovm/tests/files/type37e.gno b/gnovm/tests/files/type37e.gno index 239202ac92d..8339783d370 100644 --- a/gnovm/tests/files/type37e.gno +++ b/gnovm/tests/files/type37e.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/type37e.gno:8:1: invalid receiver type main.Int2 (base type is pointer type) +// main/type37e.gno:8:1-10:2: invalid receiver type main.Int2 (base type is pointer type) // TypeCheckError: // main/type37e.gno:8:10: invalid receiver type Int2 (pointer or interface type); main/type37e.gno:13:19: Int2(ip).Int undefined (type Int2 has no field or method Int) diff --git a/gnovm/tests/files/type37f.gno b/gnovm/tests/files/type37f.gno index 3d4e1047eef..ca2d4c156ed 100644 --- a/gnovm/tests/files/type37f.gno +++ b/gnovm/tests/files/type37f.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/type37f.gno:7:1: invalid receiver type *main.IntPtr (base type is pointer type) +// main/type37f.gno:7:1-9:2: invalid receiver type *main.IntPtr (base type is pointer type) // TypeCheckError: // main/type37f.gno:7:10: invalid receiver type IntPtr (pointer or interface type) diff --git a/gnovm/tests/files/type39.gno b/gnovm/tests/files/type39.gno index 565052a8a3f..52c1b368e92 100644 --- a/gnovm/tests/files/type39.gno +++ b/gnovm/tests/files/type39.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/type39.gno:7:1: invalid receiver type main.foo (base type is interface type) +// main/type39.gno:7:1-9:2: invalid receiver type main.foo (base type is interface type) // TypeCheckError: // main/type39.gno:7:9: invalid receiver type foo (pointer or interface type) diff --git a/gnovm/tests/files/type39a.gno b/gnovm/tests/files/type39a.gno index 7b31616ac16..7c7b5239d8b 100644 --- a/gnovm/tests/files/type39a.gno +++ b/gnovm/tests/files/type39a.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/type39a.gno:9:1: invalid receiver type main.FF (base type is interface type) +// main/type39a.gno:9:1-11:2: invalid receiver type main.FF (base type is interface type) // TypeCheckError: // main/type39a.gno:9:9: invalid receiver type FF (pointer or interface type); main/type39a.gno:20:12: f.echo undefined (type foo has no field or method echo) diff --git a/gnovm/tests/files/type39b.gno b/gnovm/tests/files/type39b.gno index e45bee03871..e98e702895d 100644 --- a/gnovm/tests/files/type39b.gno +++ b/gnovm/tests/files/type39b.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/type39b.gno:7:1: invalid receiver type *main.foo (base type is interface type) +// main/type39b.gno:7:1-9:2: invalid receiver type *main.foo (base type is interface type) // TypeCheckError: // main/type39b.gno:7:10: invalid receiver type foo (pointer or interface type); main/type39b.gno:18:12: f.echo undefined (type *foo is pointer to interface, not interface) diff --git a/gnovm/tests/files/type41.gno b/gnovm/tests/files/type41.gno index 448c67ac60a..2bb267d87d8 100644 --- a/gnovm/tests/files/type41.gno +++ b/gnovm/tests/files/type41.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/type41.gno:3:6: nil is not a type +// main/type41.gno:3:6-11: nil is not a type // TypeCheckError: // main/type41.gno:3:8: nil is not a type diff --git a/gnovm/tests/files/typeassert3.gno b/gnovm/tests/files/typeassert3.gno index 6e6c5d8a189..f75ef53fa50 100644 --- a/gnovm/tests/files/typeassert3.gno +++ b/gnovm/tests/files/typeassert3.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/typeassert3.gno:9:8: cannot use _ as value or type +// main/typeassert3.gno:9:8-9: cannot use _ as value or type // TypeCheckError: // main/typeassert3.gno:9:8: cannot use _ as value or type diff --git a/gnovm/tests/files/typeassert8.gno b/gnovm/tests/files/typeassert8.gno index f0b2460ea4e..655ad2555e0 100644 --- a/gnovm/tests/files/typeassert8.gno +++ b/gnovm/tests/files/typeassert8.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8.gno:13:7-13: invalid operation: r (variable of type []int) is not an interface // TypeCheckError: // main/typeassert8.gno:13:7: invalid operation: r (variable of type []int) is not an interface diff --git a/gnovm/tests/files/typeassert8a.gno b/gnovm/tests/files/typeassert8a.gno index 19d11578852..873db750cdb 100644 --- a/gnovm/tests/files/typeassert8a.gno +++ b/gnovm/tests/files/typeassert8a.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface +// main/typeassert8a.gno:13:11-17: invalid operation: r (variable of type []int) is not an interface // TypeCheckError: // main/typeassert8a.gno:13:11: invalid operation: r (variable of type []int) is not an interface diff --git a/gnovm/tests/files/typeassert9a.gno b/gnovm/tests/files/typeassert9a.gno index 21481f72d81..4f1ff0e8fbf 100644 --- a/gnovm/tests/files/typeassert9a.gno +++ b/gnovm/tests/files/typeassert9a.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/typeassert9a.gno:15:6: *main.csvReader does not implement main.Reader (wrong type for method Read) +// main/typeassert9a.gno:15:6-37: *main.csvReader does not implement main.Reader (wrong type for method Read) // TypeCheckError: // main/typeassert9a.gno:15:25: cannot use &csvReader{} (value of type *csvReader) as Reader value in variable declaration: *csvReader does not implement Reader (wrong type for method Read) diff --git a/gnovm/tests/files/types/add_a0.gno b/gnovm/tests/files/types/add_a0.gno index 65901991a36..9d314da760f 100644 --- a/gnovm/tests/files/types/add_a0.gno +++ b/gnovm/tests/files/types/add_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/add_a0.gno:5:10: invalid operation: (const (1 int)) + (const (1 int8)) (mismatched types int and int8) +// main/add_a0.gno:5:10-26: invalid operation: (const (1 int)) + (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/add_a0.gno:5:10: invalid operation: int(1) + int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/add_a1.gno b/gnovm/tests/files/types/add_a1.gno index 4c58e008e1a..8d14006ef90 100644 --- a/gnovm/tests/files/types/add_a1.gno +++ b/gnovm/tests/files/types/add_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/add_a1.gno:21:10: invalid operation: (const (0 main.Error1)) + (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) +// main/add_a1.gno:21:10-31: invalid operation: (const (0 main.Error1)) + (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/add_a1.gno:21:10: invalid operation: Error1(0) + Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_a0.gno b/gnovm/tests/files/types/add_assign_a0.gno index 339229efbe6..aa415e3883b 100644 --- a/gnovm/tests/files/types/add_assign_a0.gno +++ b/gnovm/tests/files/types/add_assign_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/add_assign_a0.gno:5:2: invalid operation: mismatched types int and int8 +// main/add_assign_a0.gno:5:2-19: invalid operation: mismatched types int and int8 // TypeCheckError: // main/add_assign_a0.gno:5:2: invalid operation: int(0) += int8(1) (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 index 135135c6ee7..a8ca94cf4b9 100644 --- a/gnovm/tests/files/types/add_assign_a1.gno +++ b/gnovm/tests/files/types/add_assign_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/add_assign_a1.gno:21:2: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_assign_a1.gno:21:2-24: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: // main/add_assign_a1.gno:21:2: invalid operation: Error1(0) += Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_a_01.gno b/gnovm/tests/files/types/add_assign_a_01.gno index 9963a0a7504..9d7f90a0f25 100644 --- a/gnovm/tests/files/types/add_assign_a_01.gno +++ b/gnovm/tests/files/types/add_assign_a_01.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/add_assign_a_01.gno:6:2: assignment operator += requires only one expression on lhs and rhs +// main/add_assign_a_01.gno:6:2-14: assignment operator += requires only one expression on lhs and rhs // TypeCheckError: // main/add_assign_a_01.gno:6:7: assignment operation += requires single-valued expressions diff --git a/gnovm/tests/files/types/add_assign_b0.gno b/gnovm/tests/files/types/add_assign_b0.gno index 6a030aec1ad..b465d468854 100644 --- a/gnovm/tests/files/types/add_assign_b0.gno +++ b/gnovm/tests/files/types/add_assign_b0.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/add_assign_b0.gno:8:2: invalid operation: mismatched types int and main.Error +// main/add_assign_b0.gno:8:2-15: invalid operation: mismatched types int and main.Error // TypeCheckError: // main/add_assign_b0.gno:8:2: invalid operation: r += Error(1) (mismatched types int and Error) diff --git a/gnovm/tests/files/types/add_assign_e0.gno b/gnovm/tests/files/types/add_assign_e0.gno index 38e41c8e9cc..5b0a46aa9c7 100644 --- a/gnovm/tests/files/types/add_assign_e0.gno +++ b/gnovm/tests/files/types/add_assign_e0.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/add_assign_e0.gno:23:2: invalid operation: mismatched types main.Error1 and main.Error2 +// main/add_assign_e0.gno:23:2-10: invalid operation: mismatched types main.Error1 and main.Error2 // TypeCheckError: // main/add_assign_e0.gno:23:2: invalid operation: e1 += e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_assign_f0.gno b/gnovm/tests/files/types/add_assign_f0.gno index 3c1d62941df..13599df0e8e 100644 --- a/gnovm/tests/files/types/add_assign_f0.gno +++ b/gnovm/tests/files/types/add_assign_f0.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/add_assign_f0.gno:20:2: invalid operation: mismatched types int and .uverse.error +// main/add_assign_f0.gno:20:2-13: invalid operation: mismatched types int and .uverse.error // TypeCheckError: // main/add_assign_f0.gno:20:2: invalid operation: r += errCmp (mismatched types int and error) diff --git a/gnovm/tests/files/types/add_assign_f1.gno b/gnovm/tests/files/types/add_assign_f1.gno index 707fe95c465..25d91926955 100644 --- a/gnovm/tests/files/types/add_assign_f1.gno +++ b/gnovm/tests/files/types/add_assign_f1.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/add_assign_f1.gno:21:2: invalid operation: mismatched types main.Error and .uverse.error +// main/add_assign_f1.gno:21:2-13: invalid operation: mismatched types main.Error and .uverse.error // TypeCheckError: // main/add_assign_f1.gno:21:2: invalid operation: r += errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/add_assign_f2.gno b/gnovm/tests/files/types/add_assign_f2.gno index 7f891492bbd..6bbcd2aebf1 100644 --- a/gnovm/tests/files/types/add_assign_f2.gno +++ b/gnovm/tests/files/types/add_assign_f2.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/add_assign_f2.gno:20:2: operator += not defined on: InterfaceKind +// main/add_assign_f2.gno:20:2-13: operator += not defined on: InterfaceKind // TypeCheckError: // main/add_assign_f2.gno:20:2: invalid operation: errCmp += r (mismatched types error and Error) diff --git a/gnovm/tests/files/types/add_assign_f3.gno b/gnovm/tests/files/types/add_assign_f3.gno index 87835bcf390..94bb450101f 100644 --- a/gnovm/tests/files/types/add_assign_f3.gno +++ b/gnovm/tests/files/types/add_assign_f3.gno @@ -29,7 +29,7 @@ func main() { } // Error: -// main/add_assign_f3.gno:27:2: operator += not defined on: InterfaceKind +// main/add_assign_f3.gno:27:2-10: operator += not defined on: InterfaceKind // TypeCheckError: // main/add_assign_f3.gno:27:2: invalid operation: operator + not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/add_b2.gno b/gnovm/tests/files/types/add_b2.gno index 6ba2bd821cf..7e5f709e398 100644 --- a/gnovm/tests/files/types/add_b2.gno +++ b/gnovm/tests/files/types/add_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/add_b2.gno:5:10: cannot use untyped Bigint as StringKind +// main/add_b2.gno:5:10-17: cannot use untyped Bigint as StringKind // TypeCheckError: // main/add_b2.gno:5:10: invalid operation: 1 + "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/add_d4.gno b/gnovm/tests/files/types/add_d4.gno index dd2c97d4a9c..253dd66b0b2 100644 --- a/gnovm/tests/files/types/add_d4.gno +++ b/gnovm/tests/files/types/add_d4.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/add_d4.gno:7:10: operator + not defined on: InterfaceKind +// main/add_d4.gno:7:10-15: operator + not defined on: InterfaceKind // TypeCheckError: // main/add_d4.gno:7:10: invalid operation: b + a (mismatched types any and int) diff --git a/gnovm/tests/files/types/add_e0.gno b/gnovm/tests/files/types/add_e0.gno index df6bb6d6de3..1640115f0bd 100644 --- a/gnovm/tests/files/types/add_e0.gno +++ b/gnovm/tests/files/types/add_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types main.Error1 and main.Error2) +// main/add_e0.gno:23:10-17: invalid operation: e1 + e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/add_e0.gno:23:10: invalid operation: e1 + e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/add_f0.gno b/gnovm/tests/files/types/add_f0.gno index 853a5fe3848..6c78a694430 100644 --- a/gnovm/tests/files/types/add_f0.gno +++ b/gnovm/tests/files/types/add_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/add_f0.gno:19:10: operator + not defined on: InterfaceKind +// main/add_f0.gno:19:10-20: operator + not defined on: InterfaceKind // TypeCheckError: // main/add_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/add_f1.gno b/gnovm/tests/files/types/add_f1.gno index 0d68ecbb213..0224c3c3f27 100644 --- a/gnovm/tests/files/types/add_f1.gno +++ b/gnovm/tests/files/types/add_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/add_f1.gno:19:10: operator + not defined on: InterfaceKind +// main/add_f1.gno:19:10-27: operator + not defined on: InterfaceKind // TypeCheckError: // main/add_f1.gno:19:10: invalid operation: Error(0) + errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/add_f2.gno b/gnovm/tests/files/types/add_f2.gno index 1da2b73ab49..579a3b4375d 100644 --- a/gnovm/tests/files/types/add_f2.gno +++ b/gnovm/tests/files/types/add_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/add_f2.gno:27:10: operator + not defined on: InterfaceKind +// main/add_f2.gno:27:10-17: operator + not defined on: InterfaceKind // TypeCheckError: // main/add_f2.gno:27:10: invalid operation: operator + not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/and_a0.gno b/gnovm/tests/files/types/and_a0.gno index 7ad33afb708..b7887e6de66 100644 --- a/gnovm/tests/files/types/and_a0.gno +++ b/gnovm/tests/files/types/and_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/and_a0.gno:5:10: invalid operation: (const (0 int)) & (const (1 int8)) (mismatched types int and int8) +// main/and_a0.gno:5:10-26: invalid operation: (const (0 int)) & (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/and_a0.gno:5:10: invalid operation: int(0) & int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/and_a1.gno b/gnovm/tests/files/types/and_a1.gno index 05d52a54436..7747c7125d9 100644 --- a/gnovm/tests/files/types/and_a1.gno +++ b/gnovm/tests/files/types/and_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/and_a1.gno:21:10: invalid operation: (const (0 main.Error1)) & (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) +// main/and_a1.gno:21:10-31: invalid operation: (const (0 main.Error1)) & (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/and_a1.gno:21:10: invalid operation: Error1(0) & Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_b2.gno b/gnovm/tests/files/types/and_b2.gno index 229555bfc87..6a6396176f5 100644 --- a/gnovm/tests/files/types/and_b2.gno +++ b/gnovm/tests/files/types/and_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/and_b2.gno:5:10: operator & not defined on: StringKind +// main/and_b2.gno:5:10-17: operator & not defined on: StringKind // TypeCheckError: // main/and_b2.gno:5:10: invalid operation: 1 & "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/and_b3.gno b/gnovm/tests/files/types/and_b3.gno index 8de2636ab85..a12f2571a2b 100644 --- a/gnovm/tests/files/types/and_b3.gno +++ b/gnovm/tests/files/types/and_b3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/and_b3.gno:5:10: operator & not defined on: StringKind +// main/and_b3.gno:5:10-19: operator & not defined on: StringKind // TypeCheckError: // main/and_b3.gno:5:10: invalid operation: operator & not defined on "b" (untyped string constant) diff --git a/gnovm/tests/files/types/and_d0.gno b/gnovm/tests/files/types/and_d0.gno index fc240a1e7c0..37e3d3ab2f8 100644 --- a/gnovm/tests/files/types/and_d0.gno +++ b/gnovm/tests/files/types/and_d0.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/and_d0.gno:6:10: operator & not defined on: BigdecKind +// main/and_d0.gno:6:10-17: operator & not defined on: BigdecKind // TypeCheckError: // main/and_d0.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/and_d4.gno b/gnovm/tests/files/types/and_d4.gno index 898a5065eb9..aaecee9bdda 100644 --- a/gnovm/tests/files/types/and_d4.gno +++ b/gnovm/tests/files/types/and_d4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/and_d4.gno:6:10: operator & not defined on: BigdecKind +// main/and_d4.gno:6:10-17: operator & not defined on: BigdecKind // TypeCheckError: // main/and_d4.gno:6:10: invalid operation: operator & not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/and_e0.gno b/gnovm/tests/files/types/and_e0.gno index 7dc46bdc524..d86dec60d9c 100644 --- a/gnovm/tests/files/types/and_e0.gno +++ b/gnovm/tests/files/types/and_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types main.Error1 and main.Error2) +// main/and_e0.gno:23:10-17: invalid operation: e1 & e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/and_e0.gno:23:10: invalid operation: e1 & e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/and_f0.gno b/gnovm/tests/files/types/and_f0.gno index 7cd46aedf76..521a1b6c7f9 100644 --- a/gnovm/tests/files/types/and_f0.gno +++ b/gnovm/tests/files/types/and_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/and_f0.gno:19:10: operator & not defined on: InterfaceKind +// main/and_f0.gno:19:10-20: operator & not defined on: InterfaceKind // TypeCheckError: // main/and_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/and_f1.gno b/gnovm/tests/files/types/and_f1.gno index 6902301dde2..f13791cbfa8 100644 --- a/gnovm/tests/files/types/and_f1.gno +++ b/gnovm/tests/files/types/and_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/and_f1.gno:19:10: operator & not defined on: InterfaceKind +// main/and_f1.gno:19:10-27: operator & not defined on: InterfaceKind // TypeCheckError: // main/and_f1.gno:19:10: invalid operation: Error(0) & errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/and_f2.gno b/gnovm/tests/files/types/and_f2.gno index f8ef2526d39..a283c9411c1 100644 --- a/gnovm/tests/files/types/and_f2.gno +++ b/gnovm/tests/files/types/and_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/and_f2.gno:27:10: operator & not defined on: InterfaceKind +// main/and_f2.gno:27:10-17: operator & not defined on: InterfaceKind // TypeCheckError: // main/and_f2.gno:27:10: invalid operation: operator & not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/assign_call.gno b/gnovm/tests/files/types/assign_call.gno index 260c25c866f..8eb7f3a3547 100644 --- a/gnovm/tests/files/types/assign_call.gno +++ b/gnovm/tests/files/types/assign_call.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign_call.gno:9:2: cannot use int as string +// main/assign_call.gno:9:2-15: cannot use int as string // TypeCheckError: // main/assign_call.gno:9:10: cannot use foo() (value of type int) as string value in assignment; main/assign_call.gno:9:10: cannot use foo() (value of type float32) as string value in assignment; main/assign_call.gno:8:9: declared and not used: s1 diff --git a/gnovm/tests/files/types/assign_index.gno b/gnovm/tests/files/types/assign_index.gno index 77e2364967f..ecd10e17030 100644 --- a/gnovm/tests/files/types/assign_index.gno +++ b/gnovm/tests/files/types/assign_index.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign_index.gno:8:2: cannot use int as string +// main/assign_index.gno:8:2-16: cannot use int as string // TypeCheckError: // main/assign_index.gno:8:10: cannot use m["a"] (map index expression of type int) as string value in assignment diff --git a/gnovm/tests/files/types/assign_index_a.gno b/gnovm/tests/files/types/assign_index_a.gno index 3ca128b2a83..da06a571802 100644 --- a/gnovm/tests/files/types/assign_index_a.gno +++ b/gnovm/tests/files/types/assign_index_a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign_index_a.gno:6:2: cannot use int as string +// main/assign_index_a.gno:6:2-53: cannot use int as string // TypeCheckError: // main/assign_index_a.gno:6:10: cannot use map[string]int{…}["a"] (map index expression of type int) as string value in assignment diff --git a/gnovm/tests/files/types/assign_index_b.gno b/gnovm/tests/files/types/assign_index_b.gno index 3c6f68d6c65..9ba17bc7423 100644 --- a/gnovm/tests/files/types/assign_index_b.gno +++ b/gnovm/tests/files/types/assign_index_b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign_index_b.gno:8:2: want bool type got int +// main/assign_index_b.gno:8:2-16: want bool type got int // TypeCheckError: // main/assign_index_b.gno:8:10: cannot use m["a"] (untyped bool value) as int value in assignment diff --git a/gnovm/tests/files/types/assign_index_c.gno b/gnovm/tests/files/types/assign_index_c.gno index f8063656b1c..dc9a3e2099a 100644 --- a/gnovm/tests/files/types/assign_index_c.gno +++ b/gnovm/tests/files/types/assign_index_c.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign_index_c.gno:7:2: cannot use int as string +// main/assign_index_c.gno:7:2-11: cannot use int as string // TypeCheckError: // main/assign_index_c.gno:7:7: cannot use s[0] (variable of type int) as string value in assignment; main/assign_index_c.gno:6:6: declared and not used: s1 diff --git a/gnovm/tests/files/types/assign_literal.gno b/gnovm/tests/files/types/assign_literal.gno index 6c77398885f..25fedd04c58 100644 --- a/gnovm/tests/files/types/assign_literal.gno +++ b/gnovm/tests/files/types/assign_literal.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign_literal.gno:4:2: cannot assign to (const (1 bigint)) +// main/assign_literal.gno:4:2-7: cannot assign to (const (1 bigint)) // TypeCheckError: // main/assign_literal.gno:4:2: cannot assign to 1 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal10a.gno b/gnovm/tests/files/types/assign_literal10a.gno index 0dcad609edd..eb2d29f2769 100644 --- a/gnovm/tests/files/types/assign_literal10a.gno +++ b/gnovm/tests/files/types/assign_literal10a.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/assign_literal10a.gno:13:2: cannot assign to s.add() +// main/assign_literal10a.gno:13:2-13: cannot assign to s.add() // TypeCheckError: // main/assign_literal10a.gno:13:2: cannot assign to s.add() (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal11.gno b/gnovm/tests/files/types/assign_literal11.gno index 4f107c61a5c..da80b4a8d43 100644 --- a/gnovm/tests/files/types/assign_literal11.gno +++ b/gnovm/tests/files/types/assign_literal11.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/assign_literal11.gno:6:2: cannot assign to const Pi +// main/assign_literal11.gno:6:2-14: cannot assign to const Pi // TypeCheckError: // main/assign_literal11.gno:6:2: cannot assign to Pi (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal2.gno b/gnovm/tests/files/types/assign_literal2.gno index 318fee0f1ed..5ce5897e98c 100644 --- a/gnovm/tests/files/types/assign_literal2.gno +++ b/gnovm/tests/files/types/assign_literal2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/assign_literal2.gno:5:2: cannot assign to (const (2 bigint)) +// main/assign_literal2.gno:5:2-13: cannot assign to (const (2 bigint)) // TypeCheckError: // main/assign_literal2.gno:5:5: cannot assign to 2 (neither addressable nor a map index expression); main/assign_literal2.gno:4:6: declared and not used: a diff --git a/gnovm/tests/files/types/assign_literal3.gno b/gnovm/tests/files/types/assign_literal3.gno index 1b21d220c51..b35f1182f8c 100644 --- a/gnovm/tests/files/types/assign_literal3.gno +++ b/gnovm/tests/files/types/assign_literal3.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign_literal3.gno:4:2: cannot assign to uverse true +// main/assign_literal3.gno:4:2-14: cannot assign to uverse true // TypeCheckError: // main/assign_literal3.gno:4:2: cannot assign to true (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal4.gno b/gnovm/tests/files/types/assign_literal4.gno index 73cfb0f77d8..12a26a62b4d 100644 --- a/gnovm/tests/files/types/assign_literal4.gno +++ b/gnovm/tests/files/types/assign_literal4.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign_literal4.gno:4:2: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} +// main/assign_literal4.gno:4:2-27: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} // TypeCheckError: // main/assign_literal4.gno:4:2: cannot assign to []int{…} (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal5.gno b/gnovm/tests/files/types/assign_literal5.gno index a088ebef7f2..9e39a53da5e 100644 --- a/gnovm/tests/files/types/assign_literal5.gno +++ b/gnovm/tests/files/types/assign_literal5.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign_literal5.gno:4:2: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} +// main/assign_literal5.gno:4:2-65: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} // TypeCheckError: // main/assign_literal5.gno:4:2: cannot assign to map[string]int{…} (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal6.gno b/gnovm/tests/files/types/assign_literal6.gno index d37d0b07465..2a7cd87bd11 100644 --- a/gnovm/tests/files/types/assign_literal6.gno +++ b/gnovm/tests/files/types/assign_literal6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/assign_literal6.gno:4:2: cannot assign to (const (3 bigint)) +// main/assign_literal6.gno:4:2-11: cannot assign to (const (3 bigint)) // TypeCheckError: // main/assign_literal6.gno:4:2: cannot assign to 1 + 2 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_literal7c.gno b/gnovm/tests/files/types/assign_literal7c.gno index 935869623ba..0b4a04f2049 100644 --- a/gnovm/tests/files/types/assign_literal7c.gno +++ b/gnovm/tests/files/types/assign_literal7c.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/assign_literal7c.gno:7:2: cannot assign to str[(const (0 int))] +// main/assign_literal7c.gno:7:2-14: cannot assign to str[(const (0 int))] // TypeCheckError: // main/assign_literal7c.gno:7:2: cannot assign to str[0] (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_nil.gno b/gnovm/tests/files/types/assign_nil.gno index 1c15fb0722b..7965feee8d5 100644 --- a/gnovm/tests/files/types/assign_nil.gno +++ b/gnovm/tests/files/types/assign_nil.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/assign_nil.gno:7:2: cannot assign to uverse nil +// main/assign_nil.gno:7:2-18: cannot assign to uverse nil // TypeCheckError: // main/assign_nil.gno:7:5: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil.gno:6:6: declared and not used: j diff --git a/gnovm/tests/files/types/assign_nil2.gno b/gnovm/tests/files/types/assign_nil2.gno index 3821ed56de8..99a0764a517 100644 --- a/gnovm/tests/files/types/assign_nil2.gno +++ b/gnovm/tests/files/types/assign_nil2.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/assign_nil2.gno:7:2: cannot assign to uverse nil +// main/assign_nil2.gno:7:2-20: cannot assign to uverse nil // TypeCheckError: // main/assign_nil2.gno:7:2: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil2.gno:7:7: cannot assign to nil (neither addressable nor a map index expression); main/assign_nil2.gno:6:6: declared and not used: ok diff --git a/gnovm/tests/files/types/assign_range_a.gno b/gnovm/tests/files/types/assign_range_a.gno index 49ee015c40b..fe948b1938b 100644 --- a/gnovm/tests/files/types/assign_range_a.gno +++ b/gnovm/tests/files/types/assign_range_a.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/assign_range_a.gno:16:2: cannot use string as int +// main/assign_range_a.gno:16:2-18:3: cannot use string as int // TypeCheckError: // main/assign_range_a.gno:16:6: cannot use k (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_a1.gno b/gnovm/tests/files/types/assign_range_a1.gno index 0d6cdb41d54..7569101f864 100644 --- a/gnovm/tests/files/types/assign_range_a1.gno +++ b/gnovm/tests/files/types/assign_range_a1.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/assign_range_a1.gno:16:2: cannot assign to (const (6 bigint)) +// main/assign_range_a1.gno:16:2-18:3: cannot assign to (const (6 bigint)) // TypeCheckError: // main/assign_range_a1.gno:16:6: cannot assign to 6 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_range_b.gno b/gnovm/tests/files/types/assign_range_b.gno index 55fa436c2a0..ff059e0f515 100644 --- a/gnovm/tests/files/types/assign_range_b.gno +++ b/gnovm/tests/files/types/assign_range_b.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/assign_range_b.gno:14:2: cannot use string as int +// main/assign_range_b.gno:14:2-16:3: cannot use string as int // TypeCheckError: // main/assign_range_b.gno:14:9: cannot use v (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_b1.gno b/gnovm/tests/files/types/assign_range_b1.gno index 2c6f91820a9..f9e9aa1c07f 100644 --- a/gnovm/tests/files/types/assign_range_b1.gno +++ b/gnovm/tests/files/types/assign_range_b1.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/assign_range_b1.gno:14:2: cannot use string as int +// main/assign_range_b1.gno:14:2-16:3: cannot use string as int // TypeCheckError: // main/assign_range_b1.gno:14:9: cannot use v (value of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_range_c.gno b/gnovm/tests/files/types/assign_range_c.gno index ee9e5379006..38bc23a04eb 100644 --- a/gnovm/tests/files/types/assign_range_c.gno +++ b/gnovm/tests/files/types/assign_range_c.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/assign_range_c.gno:14:2: index type should be int, but got float32 +// main/assign_range_c.gno:14:2-16:3: index type should be int, but got float32 // TypeCheckError: // main/assign_range_c.gno:14:6: cannot use k (value of type int) as float32 value in assignment; main/assign_range_c.gno:14:9: cannot use v (value of type string) as float32 value in assignment diff --git a/gnovm/tests/files/types/assign_range_d.gno b/gnovm/tests/files/types/assign_range_d.gno index d3b07d8d3b6..c5cf654f1be 100644 --- a/gnovm/tests/files/types/assign_range_d.gno +++ b/gnovm/tests/files/types/assign_range_d.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/assign_range_d.gno:8:2: index type should be int, but got float32 +// main/assign_range_d.gno:8:2-10:3: index type should be int, but got float32 // TypeCheckError: // main/assign_range_d.gno:8:6: cannot use index (value of type int) as float32 value in assignment; main/assign_range_d.gno:7:6: declared and not used: value diff --git a/gnovm/tests/files/types/assign_range_e.gno b/gnovm/tests/files/types/assign_range_e.gno index ca00cf658f5..3c85485dc85 100644 --- a/gnovm/tests/files/types/assign_range_e.gno +++ b/gnovm/tests/files/types/assign_range_e.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/assign_range_e.gno:8:2: value type should be int32, but got int +// main/assign_range_e.gno:8:2-11:3: value type should be int32, but got int // TypeCheckError: // main/assign_range_e.gno:8:13: cannot use value (value of type rune) as int value in assignment diff --git a/gnovm/tests/files/types/assign_rune_a.gno b/gnovm/tests/files/types/assign_rune_a.gno index 4e3a1db4ac6..44cfa5375d0 100644 --- a/gnovm/tests/files/types/assign_rune_a.gno +++ b/gnovm/tests/files/types/assign_rune_a.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/assign_rune_a.gno:7:2: cannot use untyped string as Int32Kind +// main/assign_rune_a.gno:7:2-9: cannot use untyped string as Int32Kind // TypeCheckError: // main/assign_rune_a.gno:7:6: cannot use "a" (untyped string constant) as rune value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion.gno b/gnovm/tests/files/types/assign_type_assertion.gno index 52fd842f36f..ceb28d84897 100644 --- a/gnovm/tests/files/types/assign_type_assertion.gno +++ b/gnovm/tests/files/types/assign_type_assertion.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/assign_type_assertion.gno:13:2: cannot use string as int +// main/assign_type_assertion.gno:13:2-20: cannot use string as int // TypeCheckError: // main/assign_type_assertion.gno:13:10: cannot use i.(string) (comma, ok expression of type string) as int value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_b.gno b/gnovm/tests/files/types/assign_type_assertion_b.gno index f0189b6e752..d0aeedd0e04 100644 --- a/gnovm/tests/files/types/assign_type_assertion_b.gno +++ b/gnovm/tests/files/types/assign_type_assertion_b.gno @@ -29,7 +29,7 @@ func main() { } // Error: -// main/assign_type_assertion_b.gno:22:2: cannot use interface {IsSet func() bool} as int +// main/assign_type_assertion_b.gno:22:2-51: cannot use interface {IsSet func() bool} as int // TypeCheckError: // main/assign_type_assertion_b.gno:22:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as int value in assignment; main/assign_type_assertion_b.gno:25:37: assertedErr.IsSet undefined (type int has no field or method IsSet) diff --git a/gnovm/tests/files/types/assign_type_assertion_c.gno b/gnovm/tests/files/types/assign_type_assertion_c.gno index 00d8b4bf380..4e2baea09bd 100644 --- a/gnovm/tests/files/types/assign_type_assertion_c.gno +++ b/gnovm/tests/files/types/assign_type_assertion_c.gno @@ -30,7 +30,7 @@ func main() { } // Error: -// main/assign_type_assertion_c.gno:23:2: interface {IsSet func() bool} does not implement interface {IsNotSet func() bool} (missing method IsNotSet) +// main/assign_type_assertion_c.gno:23:2-51: interface {IsSet func() bool} does not implement interface {IsNotSet func() bool} (missing method IsNotSet) // TypeCheckError: // main/assign_type_assertion_c.gno:23:20: cannot use err.(interface{IsSet() bool}) (comma, ok expression of type interface{IsSet() bool}) as interface{IsNotSet() bool} value in assignment: interface{IsSet() bool} does not implement interface{IsNotSet() bool} (missing method IsNotSet); main/assign_type_assertion_c.gno:26:37: assertedErr.IsSet undefined (type interface{IsNotSet() bool} has no field or method IsSet) diff --git a/gnovm/tests/files/types/assign_type_assertion_d.gno b/gnovm/tests/files/types/assign_type_assertion_d.gno index 23f940a0ebd..de4555ac6a2 100644 --- a/gnovm/tests/files/types/assign_type_assertion_d.gno +++ b/gnovm/tests/files/types/assign_type_assertion_d.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/assign_type_assertion_d.gno:19:2: cannot use main.Dog as main.Robot without explicit conversion +// main/assign_type_assertion_d.gno:19:2-18: cannot use main.Dog as main.Robot without explicit conversion // TypeCheckError: // main/assign_type_assertion_d.gno:19:6: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_e.gno b/gnovm/tests/files/types/assign_type_assertion_e.gno index 346e6404159..3880de6f144 100644 --- a/gnovm/tests/files/types/assign_type_assertion_e.gno +++ b/gnovm/tests/files/types/assign_type_assertion_e.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/assign_type_assertion_e.gno:20:2: cannot use main.Dog as main.Robot without explicit conversion +// main/assign_type_assertion_e.gno:20:2-22: cannot use main.Dog as main.Robot without explicit conversion // TypeCheckError: // main/assign_type_assertion_e.gno:20:10: cannot use animal.(Dog) (comma, ok expression of struct type Dog) as Robot value in assignment diff --git a/gnovm/tests/files/types/assign_type_assertion_f.gno b/gnovm/tests/files/types/assign_type_assertion_f.gno index 7fe443ffc33..f15f6d705c9 100644 --- a/gnovm/tests/files/types/assign_type_assertion_f.gno +++ b/gnovm/tests/files/types/assign_type_assertion_f.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/assign_type_assertion_f.gno:19:2: cannot assign to (const (1 bigint)) +// main/assign_type_assertion_f.gno:19:2-22: cannot assign to (const (1 bigint)) // TypeCheckError: // main/assign_type_assertion_f.gno:19:2: cannot assign to 1 (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/types/assign_type_assertion_g.gno b/gnovm/tests/files/types/assign_type_assertion_g.gno index 358fab8aec5..7443a7fa640 100644 --- a/gnovm/tests/files/types/assign_type_assertion_g.gno +++ b/gnovm/tests/files/types/assign_type_assertion_g.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/assign_type_assertion_g.gno:20:2: want bool type got int +// main/assign_type_assertion_g.gno:20:2-22: want bool type got int // TypeCheckError: // main/assign_type_assertion_g.gno:20:10: cannot use animal.(Dog) (untyped bool value) as int value in assignment diff --git a/gnovm/tests/files/types/bigdec2.gno b/gnovm/tests/files/types/bigdec2.gno index 94c0b3edd6f..e3da2b13c5c 100644 --- a/gnovm/tests/files/types/bigdec2.gno +++ b/gnovm/tests/files/types/bigdec2.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/bigdec2.gno:7:10: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/bigdec2.gno:7:10-17: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: // main/bigdec2.gno:7:14: 1.2 (untyped float constant) truncated to uint64 diff --git a/gnovm/tests/files/types/bigdec5.gno b/gnovm/tests/files/types/bigdec5.gno index 57a8d20bc91..0d5f3e38c60 100644 --- a/gnovm/tests/files/types/bigdec5.gno +++ b/gnovm/tests/files/types/bigdec5.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/bigdec5.gno:6:2: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/bigdec5.gno:6:2-9: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: // main/bigdec5.gno:6:6: cannot use 1.2 (untyped float constant) as uint64 value in assignment (truncated) diff --git a/gnovm/tests/files/types/bigdec_6.gno b/gnovm/tests/files/types/bigdec_6.gno index ca3af93c77c..f3c875a7bad 100644 --- a/gnovm/tests/files/types/bigdec_6.gno +++ b/gnovm/tests/files/types/bigdec_6.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/bigdec_6.gno:4:10: operator % not defined on: BigdecKind +// main/bigdec_6.gno:4:10-17: operator % not defined on: BigdecKind // TypeCheckError: // main/bigdec_6.gno:4:10: invalid operation: operator % not defined on 1 (untyped float constant) diff --git a/gnovm/tests/files/types/cmp_array_b.gno b/gnovm/tests/files/types/cmp_array_b.gno index 80cd39fe112..f4b361a0562 100644 --- a/gnovm/tests/files/types/cmp_array_b.gno +++ b/gnovm/tests/files/types/cmp_array_b.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/cmp_array_b.gno:10:25: [2][]int is not comparable +// main/cmp_array_b.gno:10:25-31: [2][]int is not comparable // TypeCheckError: // main/cmp_array_b.gno:10:25: invalid operation: a == b ([2][]int cannot be compared); main/cmp_array_b.gno:11:25: invalid operation: a == c ([2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_array_c.gno b/gnovm/tests/files/types/cmp_array_c.gno index 7db78799800..fdd62097f0f 100644 --- a/gnovm/tests/files/types/cmp_array_c.gno +++ b/gnovm/tests/files/types/cmp_array_c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/cmp_array_c.gno:10:25: [2][]int is not comparable +// main/cmp_array_c.gno:10:25-31: [2][]int is not comparable // TypeCheckError: // main/cmp_array_c.gno:10:25: invalid operation: a == b ([2][2][]int cannot be compared); main/cmp_array_c.gno:11:25: invalid operation: a == c ([2][2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_iface_5.gno b/gnovm/tests/files/types/cmp_iface_5.gno index 350c6ea50cf..a3875fa57b8 100644 --- a/gnovm/tests/files/types/cmp_iface_5.gno +++ b/gnovm/tests/files/types/cmp_iface_5.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/cmp_iface_5.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/cmp_iface_5.gno:19:5-23: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: // main/cmp_iface_5.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno index e9e10e1c5ed..f1354c9a69b 100644 --- a/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno +++ b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/cmp_iface_5_stdlibs.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/cmp_iface_5_stdlibs.gno:19:5-23: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: // main/cmp_iface_5_stdlibs.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/cmp_pointer.gno b/gnovm/tests/files/types/cmp_pointer.gno index 79f6b173eea..d0a924f8c30 100644 --- a/gnovm/tests/files/types/cmp_pointer.gno +++ b/gnovm/tests/files/types/cmp_pointer.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/cmp_pointer.gno:19:27: cannot use main.Person as main.Worker without explicit conversion +// main/cmp_pointer.gno:19:27-38: cannot use main.Person as main.Worker without explicit conversion // TypeCheckError: // main/cmp_pointer.gno:19:33: invalid operation: p1 == p2Ptr (mismatched types *Person and *Worker) diff --git a/gnovm/tests/files/types/cmp_primitive_1.gno b/gnovm/tests/files/types/cmp_primitive_1.gno index 29395c742e7..a27338cd7c0 100644 --- a/gnovm/tests/files/types/cmp_primitive_1.gno +++ b/gnovm/tests/files/types/cmp_primitive_1.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/cmp_primitive_1.gno:14:5: cannot use untyped Bigint as StringKind +// main/cmp_primitive_1.gno:14:5-18: cannot use untyped Bigint as StringKind // TypeCheckError: // main/cmp_primitive_1.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) diff --git a/gnovm/tests/files/types/cmp_slice_4.gno b/gnovm/tests/files/types/cmp_slice_4.gno index 45845d69d0a..295513ddf97 100644 --- a/gnovm/tests/files/types/cmp_slice_4.gno +++ b/gnovm/tests/files/types/cmp_slice_4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/cmp_slice_4.gno:6:10: cannot use int as string +// main/cmp_slice_4.gno:6:10-23: cannot use int as string // TypeCheckError: // main/cmp_slice_4.gno:6:15: invalid operation: a == expected (mismatched types int and string) diff --git a/gnovm/tests/files/types/cmp_struct_a.gno b/gnovm/tests/files/types/cmp_struct_a.gno index 74b6865ee11..d3d9c8e48e3 100644 --- a/gnovm/tests/files/types/cmp_struct_a.gno +++ b/gnovm/tests/files/types/cmp_struct_a.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/cmp_struct_a.gno:15:25: [2][]int is not comparable +// main/cmp_struct_a.gno:15:25-31: [2][]int is not comparable // TypeCheckError: // main/cmp_struct_a.gno:15:25: invalid operation: a == b (struct containing [2][2][]int cannot be compared); main/cmp_struct_a.gno:16:25: invalid operation: a == c (struct containing [2][2][]int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_struct_b.gno b/gnovm/tests/files/types/cmp_struct_b.gno index 8d1ae12ca8b..2ae146ca906 100644 --- a/gnovm/tests/files/types/cmp_struct_b.gno +++ b/gnovm/tests/files/types/cmp_struct_b.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/cmp_struct_b.gno:15:10: cannot use main.foo as main.bar without explicit conversion +// main/cmp_struct_b.gno:15:10-18: cannot use main.foo as main.bar without explicit conversion // TypeCheckError: // main/cmp_struct_b.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_c.gno b/gnovm/tests/files/types/cmp_struct_c.gno index 769d217eeb4..955cc4a02cf 100644 --- a/gnovm/tests/files/types/cmp_struct_c.gno +++ b/gnovm/tests/files/types/cmp_struct_c.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/cmp_struct_c.gno:15:10: main.bar is not comparable +// main/cmp_struct_c.gno:15:10-18: main.bar is not comparable // TypeCheckError: // main/cmp_struct_c.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_c1.gno b/gnovm/tests/files/types/cmp_struct_c1.gno index b09f14c116f..d7bc2bc248a 100644 --- a/gnovm/tests/files/types/cmp_struct_c1.gno +++ b/gnovm/tests/files/types/cmp_struct_c1.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/cmp_struct_c1.gno:15:10: cannot use main.bar as main.foo without explicit conversion +// main/cmp_struct_c1.gno:15:10-18: cannot use main.bar as main.foo without explicit conversion // TypeCheckError: // main/cmp_struct_c1.gno:15:16: invalid operation: bb == fa (mismatched types bar and foo) diff --git a/gnovm/tests/files/types/cmp_struct_d.gno b/gnovm/tests/files/types/cmp_struct_d.gno index a7388d83d67..114187ce35d 100644 --- a/gnovm/tests/files/types/cmp_struct_d.gno +++ b/gnovm/tests/files/types/cmp_struct_d.gno @@ -16,7 +16,7 @@ func main() { } // Error: -// main/cmp_struct_d.gno:15:10: main.bar is not comparable +// main/cmp_struct_d.gno:15:10-18: main.bar is not comparable // TypeCheckError: // main/cmp_struct_d.gno:15:16: invalid operation: fa == bb (mismatched types foo and bar) diff --git a/gnovm/tests/files/types/cmp_struct_e.gno b/gnovm/tests/files/types/cmp_struct_e.gno index 9cb878548e4..4782ffa7f32 100644 --- a/gnovm/tests/files/types/cmp_struct_e.gno +++ b/gnovm/tests/files/types/cmp_struct_e.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/cmp_struct_e.gno:11:10: main.foo is not comparable +// main/cmp_struct_e.gno:11:10-18: main.foo is not comparable // TypeCheckError: // main/cmp_struct_e.gno:11:10: invalid operation: fa == fb (struct containing []int cannot be compared) diff --git a/gnovm/tests/files/types/cmp_struct_g.gno b/gnovm/tests/files/types/cmp_struct_g.gno index 8868515deec..35d993b25ce 100644 --- a/gnovm/tests/files/types/cmp_struct_g.gno +++ b/gnovm/tests/files/types/cmp_struct_g.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/cmp_struct_g.gno:17:25: cannot use main.Person as main.Dog without explicit conversion +// main/cmp_struct_g.gno:17:25-31: cannot use main.Person as main.Dog without explicit conversion // TypeCheckError: // main/cmp_struct_g.gno:17:30: invalid operation: a == b (mismatched types Person and Dog) diff --git a/gnovm/tests/files/types/eql_0a0.gno b/gnovm/tests/files/types/eql_0a0.gno index 912039e9e14..1e679ec01f3 100644 --- a/gnovm/tests/files/types/eql_0a0.gno +++ b/gnovm/tests/files/types/eql_0a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/eql_0a0.gno:5:10: cannot use int as int8 +// main/eql_0a0.gno:5:10-27: cannot use int as int8 // TypeCheckError: // main/eql_0a0.gno:5:20: invalid operation: int(1) == int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/eql_0a01.gno b/gnovm/tests/files/types/eql_0a01.gno index 632a0675cc1..53c03e2bfcf 100644 --- a/gnovm/tests/files/types/eql_0a01.gno +++ b/gnovm/tests/files/types/eql_0a01.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/eql_0a01.gno:4:10: is not comparable +// main/eql_0a01.gno:4:10-20: is not comparable // TypeCheckError: // main/eql_0a01.gno:4:17: invalid operation: nil == nil (operator == not defined on untyped nil) diff --git a/gnovm/tests/files/types/eql_0a02.gno b/gnovm/tests/files/types/eql_0a02.gno index 167169ca770..fa78f00faac 100644 --- a/gnovm/tests/files/types/eql_0a02.gno +++ b/gnovm/tests/files/types/eql_0a02.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/eql_0a02.gno:7:10: cannot use *int as string +// main/eql_0a02.gno:7:10-21: cannot use *int as string // TypeCheckError: // main/eql_0a02.gno:7:20: invalid operation: intPtr == s (mismatched types *int and string) diff --git a/gnovm/tests/files/types/eql_0a03.gno b/gnovm/tests/files/types/eql_0a03.gno index 916e3efe5d2..0f514b58cfa 100644 --- a/gnovm/tests/files/types/eql_0a03.gno +++ b/gnovm/tests/files/types/eql_0a03.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/eql_0a03.gno:8:10: cannot use int8 as int +// main/eql_0a03.gno:8:10-22: cannot use int8 as int // TypeCheckError: // main/eql_0a03.gno:8:20: invalid operation: intPtr == &i (mismatched types *int8 and *int) diff --git a/gnovm/tests/files/types/eql_0a1.gno b/gnovm/tests/files/types/eql_0a1.gno index a25380793f4..d7b2e8f66a5 100644 --- a/gnovm/tests/files/types/eql_0a1.gno +++ b/gnovm/tests/files/types/eql_0a1.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/eql_0a1.gno:5:10: cannot use int as int8 +// main/eql_0a1.gno:5:10-27: cannot use int as int8 // TypeCheckError: // main/eql_0a1.gno:5:20: invalid operation: int(1) != int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/eql_0a1a0.gno b/gnovm/tests/files/types/eql_0a1a0.gno index f2f5c335f6f..ebea69b120c 100644 --- a/gnovm/tests/files/types/eql_0a1a0.gno +++ b/gnovm/tests/files/types/eql_0a1a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/eql_0a1a0.gno:5:10: cannot use uint64 as uint +// main/eql_0a1a0.gno:5:10-24: cannot use uint64 as uint // TypeCheckError: // main/eql_0a1a0.gno:5:23: invalid operation: uint64(1) == a (mismatched types uint64 and uint) diff --git a/gnovm/tests/files/types/eql_0a1a1.gno b/gnovm/tests/files/types/eql_0a1a1.gno index 8d90071bc54..770c4970b89 100644 --- a/gnovm/tests/files/types/eql_0a1a1.gno +++ b/gnovm/tests/files/types/eql_0a1a1.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/eql_0a1a1.gno:5:10: cannot use uint as uint64 +// main/eql_0a1a1.gno:5:10-24: cannot use uint as uint64 // TypeCheckError: // main/eql_0a1a1.gno:5:15: invalid operation: a == uint64(1) (mismatched types uint and uint64) diff --git a/gnovm/tests/files/types/eql_0a1f.gno b/gnovm/tests/files/types/eql_0a1f.gno index e9062a74869..8138d120ce3 100644 --- a/gnovm/tests/files/types/eql_0a1f.gno +++ b/gnovm/tests/files/types/eql_0a1f.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/eql_0a1f.gno:6:10: cannot use int as string +// main/eql_0a1f.gno:6:10-23: cannot use int as string // TypeCheckError: // main/eql_0a1f.gno:6:15: invalid operation: a == expected (mismatched types int and string) diff --git a/gnovm/tests/files/types/eql_0a1g.gno b/gnovm/tests/files/types/eql_0a1g.gno index 1c1f4e3df15..3233665295b 100644 --- a/gnovm/tests/files/types/eql_0a1g.gno +++ b/gnovm/tests/files/types/eql_0a1g.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/eql_0a1g.gno:6:10: cannot use int as float32 +// main/eql_0a1g.gno:6:10-16: cannot use int as float32 // TypeCheckError: // main/eql_0a1g.gno:6:15: invalid operation: a == b (mismatched types int and float32) diff --git a/gnovm/tests/files/types/eql_0a2.gno b/gnovm/tests/files/types/eql_0a2.gno index 5954e1fff6b..2f6eefc9847 100644 --- a/gnovm/tests/files/types/eql_0a2.gno +++ b/gnovm/tests/files/types/eql_0a2.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/eql_0a2.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a2.gno:21:10-32: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: // main/eql_0a2.gno:21:23: invalid operation: Error1(0) == Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0a3.gno b/gnovm/tests/files/types/eql_0a3.gno index f2120fec151..f199efe23a6 100644 --- a/gnovm/tests/files/types/eql_0a3.gno +++ b/gnovm/tests/files/types/eql_0a3.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/eql_0a3.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a3.gno:21:10-32: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: // main/eql_0a3.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0a4.gno b/gnovm/tests/files/types/eql_0a4.gno index 77be98555cd..23638255bff 100644 --- a/gnovm/tests/files/types/eql_0a4.gno +++ b/gnovm/tests/files/types/eql_0a4.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/eql_0a4.gno:21:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0a4.gno:21:10-32: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: // main/eql_0a4.gno:21:23: invalid operation: Error1(0) != Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0b2.gno b/gnovm/tests/files/types/eql_0b2.gno index 7e5cfabda20..9097c69e0b4 100644 --- a/gnovm/tests/files/types/eql_0b2.gno +++ b/gnovm/tests/files/types/eql_0b2.gno @@ -19,7 +19,7 @@ func main() { } // Error: -// main/eql_0b2.gno:14:5: cannot use untyped Bigint as StringKind +// main/eql_0b2.gno:14:5-18: cannot use untyped Bigint as StringKind // TypeCheckError: // main/eql_0b2.gno:14:10: invalid operation: 1 == Error(1) (mismatched types untyped int and Error) diff --git a/gnovm/tests/files/types/eql_0b4.gno b/gnovm/tests/files/types/eql_0b4.gno index 9cab0f59c20..ae0d7d41ae1 100644 --- a/gnovm/tests/files/types/eql_0b4.gno +++ b/gnovm/tests/files/types/eql_0b4.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/eql_0b4.gno:9:10: bigint does not implement .uverse.error (missing method Error) +// main/eql_0b4.gno:9:10-21: bigint does not implement .uverse.error (missing method Error) // TypeCheckError: // main/eql_0b4.gno:9:10: cannot convert 5 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/eql_0c2.gno b/gnovm/tests/files/types/eql_0c2.gno index b51f8aeb902..c50b1a0a586 100644 --- a/gnovm/tests/files/types/eql_0c2.gno +++ b/gnovm/tests/files/types/eql_0c2.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/eql_0c2.gno:16:5: bigint overflows target kind +// main/eql_0c2.gno:16:5-20: bigint overflows target kind // TypeCheckError: // main/eql_0c2.gno:16:17: 128 (untyped int constant) overflows int8 diff --git a/gnovm/tests/files/types/eql_0e0.gno b/gnovm/tests/files/types/eql_0e0.gno index 0e0220ed396..45189384e56 100644 --- a/gnovm/tests/files/types/eql_0e0.gno +++ b/gnovm/tests/files/types/eql_0e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/eql_0e0.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0e0.gno:23:10-18: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: // main/eql_0e0.gno:23:16: invalid operation: e1 == e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0e1.gno b/gnovm/tests/files/types/eql_0e1.gno index 121e57a8017..4d356e9b632 100644 --- a/gnovm/tests/files/types/eql_0e1.gno +++ b/gnovm/tests/files/types/eql_0e1.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/eql_0e1.gno:23:10: cannot use main.Error1 as main.Error2 without explicit conversion +// main/eql_0e1.gno:23:10-18: cannot use main.Error1 as main.Error2 without explicit conversion // TypeCheckError: // main/eql_0e1.gno:23:16: invalid operation: e1 != e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/eql_0f0.gno b/gnovm/tests/files/types/eql_0f0.gno index 11ab657488d..05dd68643c1 100644 --- a/gnovm/tests/files/types/eql_0f0.gno +++ b/gnovm/tests/files/types/eql_0f0.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/eql_0f0.gno:19:5: bigint does not implement .uverse.error (missing method Error) +// main/eql_0f0.gno:19:5-16: bigint does not implement .uverse.error (missing method Error) // TypeCheckError: // main/eql_0f0.gno:19:5: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/eql_0f1.gno b/gnovm/tests/files/types/eql_0f1.gno index 4073d4c5db2..f9a1342c300 100644 --- a/gnovm/tests/files/types/eql_0f1.gno +++ b/gnovm/tests/files/types/eql_0f1.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/eql_0f1.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/eql_0f1.gno:19:5-23: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: // main/eql_0f1.gno:19:17: invalid operation: int64(1) == errCmp (mismatched types int64 and error) diff --git a/gnovm/tests/files/types/eql_0f14.gno b/gnovm/tests/files/types/eql_0f14.gno index cf30a3a6fc7..c4c508a7521 100644 --- a/gnovm/tests/files/types/eql_0f14.gno +++ b/gnovm/tests/files/types/eql_0f14.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/eql_0f14.gno:10:10: cannot use [2]string as [2]int +// main/eql_0f14.gno:10:10-16: cannot use [2]string as [2]int // TypeCheckError: // main/eql_0f14.gno:10:15: invalid operation: a == c (mismatched types [2]string and [2]int) diff --git a/gnovm/tests/files/types/eql_0f16.gno b/gnovm/tests/files/types/eql_0f16.gno index 19fa2cccd3a..3eb9293e56e 100644 --- a/gnovm/tests/files/types/eql_0f16.gno +++ b/gnovm/tests/files/types/eql_0f16.gno @@ -17,7 +17,7 @@ func main() { } // Error: -// main/eql_0f16.gno:16:10: [2]main.word is not comparable +// main/eql_0f16.gno:16:10-16: [2]main.word is not comparable // TypeCheckError: // main/eql_0f16.gno:16:10: invalid operation: a == c ([2]word cannot be compared) diff --git a/gnovm/tests/files/types/eql_0f17.gno b/gnovm/tests/files/types/eql_0f17.gno index b71cab3209e..ff578389710 100644 --- a/gnovm/tests/files/types/eql_0f17.gno +++ b/gnovm/tests/files/types/eql_0f17.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/eql_0f17.gno:9:10: main.f can only be compared to nil +// main/eql_0f17.gno:9:10-16: main.f can only be compared to nil // TypeCheckError: // main/eql_0f17.gno:9:10: invalid operation: a == b (func can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f20.gno b/gnovm/tests/files/types/eql_0f20.gno index b752c922410..4141b4b8eed 100644 --- a/gnovm/tests/files/types/eql_0f20.gno +++ b/gnovm/tests/files/types/eql_0f20.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/eql_0f20.gno:9:10: [2]main.f is not comparable +// main/eql_0f20.gno:9:10-18: [2]main.f is not comparable // TypeCheckError: // main/eql_0f20.gno:9:15: invalid operation: a == nil (mismatched types [2]f and untyped nil) diff --git a/gnovm/tests/files/types/eql_0f21.gno b/gnovm/tests/files/types/eql_0f21.gno index 433252392b7..43e0aaff164 100644 --- a/gnovm/tests/files/types/eql_0f21.gno +++ b/gnovm/tests/files/types/eql_0f21.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/eql_0f21.gno:9:10: [2]main.f is not comparable +// main/eql_0f21.gno:9:10-16: [2]main.f is not comparable // TypeCheckError: // main/eql_0f21.gno:9:10: invalid operation: a == b ([2]f cannot be compared) diff --git a/gnovm/tests/files/types/eql_0f27.gno b/gnovm/tests/files/types/eql_0f27.gno index 324a88c790f..6ea7ad1775d 100644 --- a/gnovm/tests/files/types/eql_0f27.gno +++ b/gnovm/tests/files/types/eql_0f27.gno @@ -18,7 +18,7 @@ func main() { } // Error: -// main/eql_0f27.gno:13:5: operator > not defined on: InterfaceKind +// main/eql_0f27.gno:13:5-22: operator > not defined on: InterfaceKind // TypeCheckError: // main/eql_0f27.gno:13:5: invalid operation: errCmp1 > errCmp2 (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f28.gno b/gnovm/tests/files/types/eql_0f28.gno index ad4980b4661..b7e69d25a08 100644 --- a/gnovm/tests/files/types/eql_0f28.gno +++ b/gnovm/tests/files/types/eql_0f28.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/eql_0f28.gno:27:10: operator > not defined on: InterfaceKind +// main/eql_0f28.gno:27:10-17: operator > not defined on: InterfaceKind // TypeCheckError: // main/eql_0f28.gno:27:10: invalid operation: e1 > e2 (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f29.gno b/gnovm/tests/files/types/eql_0f29.gno index f15ffa0f7f0..47c5ceb654f 100644 --- a/gnovm/tests/files/types/eql_0f29.gno +++ b/gnovm/tests/files/types/eql_0f29.gno @@ -21,7 +21,7 @@ func main() { } // Error: -// main/eql_0f29.gno:16:5: operator > not defined on: InterfaceKind +// main/eql_0f29.gno:16:5-17: operator > not defined on: InterfaceKind // TypeCheckError: // main/eql_0f29.gno:16:5: invalid operation: l > Error(0) (operator > not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f2b.gno b/gnovm/tests/files/types/eql_0f2b.gno index fe831661608..c0b8956b2cf 100644 --- a/gnovm/tests/files/types/eql_0f2b.gno +++ b/gnovm/tests/files/types/eql_0f2b.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/eql_0f2b.gno:19:5: operator <= not defined on: InterfaceKind +// main/eql_0f2b.gno:19:5-23: operator <= not defined on: InterfaceKind // TypeCheckError: // main/eql_0f2b.gno:19:17: invalid operation: Error(0) <= errCmp (operator <= not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f2c.gno b/gnovm/tests/files/types/eql_0f2c.gno index af0f55c4028..98768e74fe8 100644 --- a/gnovm/tests/files/types/eql_0f2c.gno +++ b/gnovm/tests/files/types/eql_0f2c.gno @@ -25,7 +25,7 @@ func main() { } // Error: -// main/eql_0f2c.gno:19:5: operator < not defined on: InterfaceKind +// main/eql_0f2c.gno:19:5-22: operator < not defined on: InterfaceKind // TypeCheckError: // main/eql_0f2c.gno:19:16: invalid operation: Error(0) < errCmp (operator < not defined on interface) diff --git a/gnovm/tests/files/types/eql_0f30.gno b/gnovm/tests/files/types/eql_0f30.gno index c9abe621494..7c0ec9a2e82 100644 --- a/gnovm/tests/files/types/eql_0f30.gno +++ b/gnovm/tests/files/types/eql_0f30.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/eql_0f30.gno:5:10: []uint8 can only be compared to nil +// main/eql_0f30.gno:5:10-36: []uint8 can only be compared to nil // TypeCheckError: // main/eql_0f30.gno:5:10: invalid operation: []byte("a") == []byte("b") (slice can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30a.gno b/gnovm/tests/files/types/eql_0f30a.gno index 26eb4fa28a0..38607e7eff8 100644 --- a/gnovm/tests/files/types/eql_0f30a.gno +++ b/gnovm/tests/files/types/eql_0f30a.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/eql_0f30a.gno:4:10: map[string]int can only be compared to nil +// main/eql_0f30a.gno:4:10-58: map[string]int can only be compared to nil // TypeCheckError: // main/eql_0f30a.gno:4:10: invalid operation: map[string]int{…} == map[string]int{…} (map can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30b.gno b/gnovm/tests/files/types/eql_0f30b.gno index 00b85e4ebc2..0948c9b0fdf 100644 --- a/gnovm/tests/files/types/eql_0f30b.gno +++ b/gnovm/tests/files/types/eql_0f30b.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/eql_0f30b.gno:9:10: main.f can only be compared to nil +// main/eql_0f30b.gno:9:10-18: main.f can only be compared to nil // TypeCheckError: // main/eql_0f30b.gno:9:10: invalid operation: f1 == f2 (func can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30d.gno b/gnovm/tests/files/types/eql_0f30d.gno index bc501866fbf..7b74b955465 100644 --- a/gnovm/tests/files/types/eql_0f30d.gno +++ b/gnovm/tests/files/types/eql_0f30d.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/eql_0f30d.gno:4:10: []int can only be compared to nil +// main/eql_0f30d.gno:4:10-30: []int can only be compared to nil // TypeCheckError: // main/eql_0f30d.gno:4:10: invalid operation: []int{…} == []int{…} (slice can only be compared to nil) diff --git a/gnovm/tests/files/types/eql_0f30f.gno b/gnovm/tests/files/types/eql_0f30f.gno index 18c582f7fa3..4950076d315 100644 --- a/gnovm/tests/files/types/eql_0f30f.gno +++ b/gnovm/tests/files/types/eql_0f30f.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/eql_0f30f.gno:7:10: cannot use [2]int as [3]int +// main/eql_0f30f.gno:7:10-16: cannot use [2]int as [3]int // TypeCheckError: // main/eql_0f30f.gno:7:15: invalid operation: a == b (mismatched types [2]int and [3]int) diff --git a/gnovm/tests/files/types/eql_0f30g.gno b/gnovm/tests/files/types/eql_0f30g.gno index b39286ee1df..344df0f9002 100644 --- a/gnovm/tests/files/types/eql_0f30g.gno +++ b/gnovm/tests/files/types/eql_0f30g.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/eql_0f30g.gno:7:10: []int can only be compared to nil +// main/eql_0f30g.gno:7:10-16: []int can only be compared to nil // TypeCheckError: // main/eql_0f30g.gno:7:15: invalid operation: a == b (mismatched types [2]int and []int) diff --git a/gnovm/tests/files/types/eql_0f41.gno b/gnovm/tests/files/types/eql_0f41.gno index 600b829441a..e244b23af71 100644 --- a/gnovm/tests/files/types/eql_0f41.gno +++ b/gnovm/tests/files/types/eql_0f41.gno @@ -32,7 +32,7 @@ func main() { } // Error: -// main/eql_0f41.gno:27:5: main.animal does not implement .uverse.error (missing method Error) +// main/eql_0f41.gno:27:5-20: main.animal does not implement .uverse.error (missing method Error) // TypeCheckError: // main/eql_0f41.gno:27:14: invalid operation: get() == errCmp (mismatched types animal and error) diff --git a/gnovm/tests/files/types/eql_0f8.gno b/gnovm/tests/files/types/eql_0f8.gno index 8045fddf5a8..46e0b909ce1 100644 --- a/gnovm/tests/files/types/eql_0f8.gno +++ b/gnovm/tests/files/types/eql_0f8.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/eql_0f8.gno:19:5: int64 does not implement .uverse.error (missing method Error) +// main/eql_0f8.gno:19:5-23: int64 does not implement .uverse.error (missing method Error) // TypeCheckError: // main/eql_0f8.gno:19:15: invalid operation: errCmp == int64(1) (mismatched types error and int64) diff --git a/gnovm/tests/files/types/explicit_conversion_1.gno b/gnovm/tests/files/types/explicit_conversion_1.gno index 8864622a90b..a426ebe9d23 100644 --- a/gnovm/tests/files/types/explicit_conversion_1.gno +++ b/gnovm/tests/files/types/explicit_conversion_1.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/explicit_conversion_1.gno:7:11: cannot convert StringKind to UintKind +// main/explicit_conversion_1.gno:7:11-32: cannot convert StringKind to UintKind // TypeCheckError: // main/explicit_conversion_1.gno:7:16: cannot convert string("hello") (constant "hello" of type string) to type uint diff --git a/gnovm/tests/files/types/incdec_a1.gno b/gnovm/tests/files/types/incdec_a1.gno index da9d953e902..400dcfc8803 100644 --- a/gnovm/tests/files/types/incdec_a1.gno +++ b/gnovm/tests/files/types/incdec_a1.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/incdec_a1.gno:5:2: operator ++ not defined on: StringKind +// main/incdec_a1.gno:5:2-5: operator ++ not defined on: StringKind // TypeCheckError: // main/incdec_a1.gno:5:2: invalid operation: a++ (non-numeric type string) diff --git a/gnovm/tests/files/types/incdec_a4.gno b/gnovm/tests/files/types/incdec_a4.gno index 4d845e10233..89637ed0baa 100644 --- a/gnovm/tests/files/types/incdec_a4.gno +++ b/gnovm/tests/files/types/incdec_a4.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/incdec_a4.gno:12:2: cannot use int8 as main.Int without explicit conversion +// main/incdec_a4.gno:12:2-13: cannot use int8 as main.Int without explicit conversion // TypeCheckError: // main/incdec_a4.gno:12:6: cannot use int8(0) (constant 0 of type int8) as Int value in assignment diff --git a/gnovm/tests/files/types/nil.gno b/gnovm/tests/files/types/nil.gno index 6e9839541f3..7815ef6c07b 100644 --- a/gnovm/tests/files/types/nil.gno +++ b/gnovm/tests/files/types/nil.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/nil.gno:5:10: operator + not defined on: nil +// main/nil.gno:5:10-19: operator + not defined on: nil // TypeCheckError: // main/nil.gno:5:10: invalid operation: operator + not defined on nil diff --git a/gnovm/tests/files/types/or_a0.gno b/gnovm/tests/files/types/or_a0.gno index 7bf317bdca6..5e19afba622 100644 --- a/gnovm/tests/files/types/or_a0.gno +++ b/gnovm/tests/files/types/or_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/or_a0.gno:5:10: invalid operation: (const (0 int)) | (const (1 int8)) (mismatched types int and int8) +// main/or_a0.gno:5:10-26: invalid operation: (const (0 int)) | (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/or_a0.gno:5:10: invalid operation: int(0) | int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/or_a1.gno b/gnovm/tests/files/types/or_a1.gno index 46f273878a6..6a9032fdd90 100644 --- a/gnovm/tests/files/types/or_a1.gno +++ b/gnovm/tests/files/types/or_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/or_a1.gno:21:10: invalid operation: (const (0 main.Error1)) | (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) +// main/or_a1.gno:21:10-31: invalid operation: (const (0 main.Error1)) | (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/or_a1.gno:21:10: invalid operation: Error1(0) | Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_b2.gno b/gnovm/tests/files/types/or_b2.gno index 110352eb03c..fca17e0ad2b 100644 --- a/gnovm/tests/files/types/or_b2.gno +++ b/gnovm/tests/files/types/or_b2.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/or_b2.gno:5:10: operator | not defined on: StringKind +// main/or_b2.gno:5:10-17: operator | not defined on: StringKind // TypeCheckError: // main/or_b2.gno:5:10: invalid operation: 1 | "a" (mismatched types untyped int and untyped string) diff --git a/gnovm/tests/files/types/or_b3.gno b/gnovm/tests/files/types/or_b3.gno index 65ba5b02c18..ee1b0996d8c 100644 --- a/gnovm/tests/files/types/or_b3.gno +++ b/gnovm/tests/files/types/or_b3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/or_b3.gno:5:10: operator | not defined on: StringKind +// main/or_b3.gno:5:10-19: operator | not defined on: StringKind // TypeCheckError: // main/or_b3.gno:5:10: invalid operation: operator | not defined on "b" (untyped string constant) diff --git a/gnovm/tests/files/types/or_d0.gno b/gnovm/tests/files/types/or_d0.gno index 5fe02318a3f..a466fdd4312 100644 --- a/gnovm/tests/files/types/or_d0.gno +++ b/gnovm/tests/files/types/or_d0.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/or_d0.gno:6:10: operator | not defined on: BigdecKind +// main/or_d0.gno:6:10-17: operator | not defined on: BigdecKind // TypeCheckError: // main/or_d0.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/or_d4.gno b/gnovm/tests/files/types/or_d4.gno index 3c3922d5621..7c55dcebd59 100644 --- a/gnovm/tests/files/types/or_d4.gno +++ b/gnovm/tests/files/types/or_d4.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/or_d4.gno:6:10: operator | not defined on: BigdecKind +// main/or_d4.gno:6:10-17: operator | not defined on: BigdecKind // TypeCheckError: // main/or_d4.gno:6:10: invalid operation: operator | not defined on 1.0 (untyped float constant 1) diff --git a/gnovm/tests/files/types/or_e0.gno b/gnovm/tests/files/types/or_e0.gno index a385c58205f..56984d45252 100644 --- a/gnovm/tests/files/types/or_e0.gno +++ b/gnovm/tests/files/types/or_e0.gno @@ -24,7 +24,7 @@ func main() { } // Error: -// main/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types main.Error1 and main.Error2) +// main/or_e0.gno:23:10-17: invalid operation: e1 | e2 (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/or_e0.gno:23:10: invalid operation: e1 | e2 (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/or_f0.gno b/gnovm/tests/files/types/or_f0.gno index 946a651ab09..fd6dca6de9d 100644 --- a/gnovm/tests/files/types/or_f0.gno +++ b/gnovm/tests/files/types/or_f0.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/or_f0.gno:19:10: operator | not defined on: InterfaceKind +// main/or_f0.gno:19:10-20: operator | not defined on: InterfaceKind // TypeCheckError: // main/or_f0.gno:19:10: cannot convert 1 (untyped int constant) to type interface{Error() string} diff --git a/gnovm/tests/files/types/or_f1.gno b/gnovm/tests/files/types/or_f1.gno index 02a9b55f474..e77d640437c 100644 --- a/gnovm/tests/files/types/or_f1.gno +++ b/gnovm/tests/files/types/or_f1.gno @@ -20,7 +20,7 @@ func main() { } // Error: -// main/or_f1.gno:19:10: operator | not defined on: InterfaceKind +// main/or_f1.gno:19:10-27: operator | not defined on: InterfaceKind // TypeCheckError: // main/or_f1.gno:19:10: invalid operation: Error(0) | errCmp (mismatched types Error and error) diff --git a/gnovm/tests/files/types/or_f2.gno b/gnovm/tests/files/types/or_f2.gno index 62f330f848e..b29d56ce028 100644 --- a/gnovm/tests/files/types/or_f2.gno +++ b/gnovm/tests/files/types/or_f2.gno @@ -28,7 +28,7 @@ func main() { } // Error: -// main/or_f2.gno:27:10: operator | not defined on: InterfaceKind +// main/or_f2.gno:27:10-17: operator | not defined on: InterfaceKind // TypeCheckError: // main/or_f2.gno:27:10: invalid operation: operator | not defined on e1 (variable of interface type E) diff --git a/gnovm/tests/files/types/rem_a0.gno b/gnovm/tests/files/types/rem_a0.gno index 53cb5fb0470..48a25429c54 100644 --- a/gnovm/tests/files/types/rem_a0.gno +++ b/gnovm/tests/files/types/rem_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/rem_a0.gno:5:10: invalid operation: (const (1 int)) % (const (1 int8)) (mismatched types int and int8) +// main/rem_a0.gno:5:10-26: invalid operation: (const (1 int)) % (const (1 int8)) (mismatched types int and int8) // TypeCheckError: // main/rem_a0.gno:5:10: invalid operation: int(1) % int8(1) (mismatched types int and int8) diff --git a/gnovm/tests/files/types/rem_a1.gno b/gnovm/tests/files/types/rem_a1.gno index 53b8faedc6f..2098b0758af 100644 --- a/gnovm/tests/files/types/rem_a1.gno +++ b/gnovm/tests/files/types/rem_a1.gno @@ -22,7 +22,7 @@ func main() { } // Error: -// main/rem_a1.gno:21:10: invalid operation: (const (0 main.Error1)) % (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) +// main/rem_a1.gno:21:10-31: invalid operation: (const (0 main.Error1)) % (const (0 main.Error2)) (mismatched types main.Error1 and main.Error2) // TypeCheckError: // main/rem_a1.gno:21:10: invalid operation: Error1(0) % Error2(0) (mismatched types Error1 and Error2) diff --git a/gnovm/tests/files/types/rem_a2.gno b/gnovm/tests/files/types/rem_a2.gno index ea1b730e968..3ff22fd2558 100644 --- a/gnovm/tests/files/types/rem_a2.gno +++ b/gnovm/tests/files/types/rem_a2.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/rem_a2.gno:4:10: invalid operation: division by zero +// main/rem_a2.gno:4:10-15: invalid operation: division by zero // TypeCheckError: // main/rem_a2.gno:4:14: invalid operation: division by zero diff --git a/gnovm/tests/files/types/rem_f3.gno b/gnovm/tests/files/types/rem_f3.gno index afcc0455fb0..e848f6fe974 100644 --- a/gnovm/tests/files/types/rem_f3.gno +++ b/gnovm/tests/files/types/rem_f3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/rem_f3.gno:5:10: invalid operation: division by zero +// main/rem_f3.gno:5:10-15: invalid operation: division by zero // TypeCheckError: // main/rem_f3.gno:5:14: invalid operation: division by zero diff --git a/gnovm/tests/files/types/runtime_a0.gno b/gnovm/tests/files/types/runtime_a0.gno index 7837471be01..621ce7092ef 100644 --- a/gnovm/tests/files/types/runtime_a0.gno +++ b/gnovm/tests/files/types/runtime_a0.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/runtime_a0.gno:5:2: operator ++ not defined on: BoolKind +// main/runtime_a0.gno:5:2-12: operator ++ not defined on: BoolKind // TypeCheckError: // main/runtime_a0.gno:5:2: invalid operation: m["foo"]++ (non-numeric type bool) diff --git a/gnovm/tests/files/types/runtime_a3.gno b/gnovm/tests/files/types/runtime_a3.gno index d9c23dc03ab..873b5d416a3 100644 --- a/gnovm/tests/files/types/runtime_a3.gno +++ b/gnovm/tests/files/types/runtime_a3.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/runtime_a3.gno:8:2: operator ++ not defined on: InterfaceKind +// main/runtime_a3.gno:8:2-9: operator ++ not defined on: InterfaceKind // TypeCheckError: // main/runtime_a3.gno:8:2: invalid operation: gen()++ (non-numeric type any) diff --git a/gnovm/tests/files/types/shift_a11.gno b/gnovm/tests/files/types/shift_a11.gno index 7d2e1572cf2..611666b1c49 100644 --- a/gnovm/tests/files/types/shift_a11.gno +++ b/gnovm/tests/files/types/shift_a11.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_a11.gno:5:7: cannot convert (const ("hello" string)) to type uint +// main/shift_a11.gno:5:7-19: cannot convert (const ("hello" string)) to type uint // TypeCheckError: // main/shift_a11.gno:5:12: cannot convert "hello" (untyped string constant) to type uint diff --git a/gnovm/tests/files/types/shift_a14.gno b/gnovm/tests/files/types/shift_a14.gno index a8aa69cf8a2..6b912d3b194 100644 --- a/gnovm/tests/files/types/shift_a14.gno +++ b/gnovm/tests/files/types/shift_a14.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_a14.gno:5:7: operator << not defined on: StringKind +// main/shift_a14.gno:5:7-13: operator << not defined on: StringKind // TypeCheckError: // main/shift_a14.gno:5:7: invalid operation: shifted operand a (variable of type string) must be integer diff --git a/gnovm/tests/files/types/shift_a15.gno b/gnovm/tests/files/types/shift_a15.gno index 0c09f586757..863c38069da 100644 --- a/gnovm/tests/files/types/shift_a15.gno +++ b/gnovm/tests/files/types/shift_a15.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_a15.gno:6:2: operator <<= not defined on: StringKind +// main/shift_a15.gno:6:2-9: operator <<= not defined on: StringKind // TypeCheckError: // main/shift_a15.gno:6:2: invalid operation: shifted operand a (variable of type string) must be integer diff --git a/gnovm/tests/files/types/shift_a16.gno b/gnovm/tests/files/types/shift_a16.gno index 9768f46d00e..420d62b1b84 100644 --- a/gnovm/tests/files/types/shift_a16.gno +++ b/gnovm/tests/files/types/shift_a16.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_a16.gno:4:7: operator << not defined on: StringKind +// main/shift_a16.gno:4:7-19: operator << not defined on: StringKind // TypeCheckError: // main/shift_a16.gno:4:7: invalid operation: shifted operand "hello" (untyped string constant) must be integer diff --git a/gnovm/tests/files/types/shift_a3.gno b/gnovm/tests/files/types/shift_a3.gno index bafb206a416..243caac9a00 100644 --- a/gnovm/tests/files/types/shift_a3.gno +++ b/gnovm/tests/files/types/shift_a3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_a3.gno:5:2: bigint overflows target kind +// main/shift_a3.gno:5:2-19: bigint overflows target kind // TypeCheckError: // main/shift_a3.gno:5:10: cannot use 1 << 'a' (untyped int constant 158456325028528675187087900672) as int value in argument to built-in println (overflows) diff --git a/gnovm/tests/files/types/shift_a7.gno b/gnovm/tests/files/types/shift_a7.gno index f8296e418a2..6efb9981efb 100644 --- a/gnovm/tests/files/types/shift_a7.gno +++ b/gnovm/tests/files/types/shift_a7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_a7.gno:5:10: cannot convert (const ("a" string)) to type uint +// main/shift_a7.gno:5:10-18: cannot convert (const ("a" string)) to type uint // TypeCheckError: // main/shift_a7.gno:5:15: cannot convert "a" (untyped string constant) to type uint diff --git a/gnovm/tests/files/types/shift_b6.gno b/gnovm/tests/files/types/shift_b6.gno index 2799b973982..040e2e5f781 100644 --- a/gnovm/tests/files/types/shift_b6.gno +++ b/gnovm/tests/files/types/shift_b6.gno @@ -27,7 +27,7 @@ func main() { } // Error: -// main/shift_b6.gno:22:2: bigint does not implement main.R (missing method foo) +// main/shift_b6.gno:22:2-12: bigint does not implement main.R (missing method foo) // TypeCheckError: // main/shift_b6.gno:22:6: cannot use 1 << x (value of type int) as R value in assignment: int does not implement R (missing method foo) diff --git a/gnovm/tests/files/types/shift_b7.gno b/gnovm/tests/files/types/shift_b7.gno index 81321a947a8..192e949c4f2 100644 --- a/gnovm/tests/files/types/shift_b7.gno +++ b/gnovm/tests/files/types/shift_b7.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/shift_b7.gno:7:7: operator << not defined on: Float32Kind +// main/shift_b7.gno:7:7-24: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_b7.gno:7:15: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c6.gno b/gnovm/tests/files/types/shift_c6.gno index ec4ad707972..d8fa13c399c 100644 --- a/gnovm/tests/files/types/shift_c6.gno +++ b/gnovm/tests/files/types/shift_c6.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/shift_c6.gno:8:2: operator << not defined on: Float32Kind +// main/shift_c6.gno:8:2-12: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_c6.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c7.gno b/gnovm/tests/files/types/shift_c7.gno index 35c0c146a63..093be5f067c 100644 --- a/gnovm/tests/files/types/shift_c7.gno +++ b/gnovm/tests/files/types/shift_c7.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/shift_c7.gno:8:2: operator << not defined on: Float32Kind +// main/shift_c7.gno:8:2-14: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_c7.gno:8:6: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_c8.gno b/gnovm/tests/files/types/shift_c8.gno index 15b79bbf4b9..269f9340a56 100644 --- a/gnovm/tests/files/types/shift_c8.gno +++ b/gnovm/tests/files/types/shift_c8.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/shift_c8.gno:8:2: cannot use int as float32 +// main/shift_c8.gno:8:2-19: cannot use int as float32 // TypeCheckError: // main/shift_c8.gno:8:6: cannot use 1 << x + int(1) (value of type int) as float32 value in assignment diff --git a/gnovm/tests/files/types/shift_d12.gno b/gnovm/tests/files/types/shift_d12.gno index aa204b7c147..0972245a764 100644 --- a/gnovm/tests/files/types/shift_d12.gno +++ b/gnovm/tests/files/types/shift_d12.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/shift_d12.gno:12:2: operator >> not defined on: Float32Kind +// main/shift_d12.gno:12:2-17: operator >> not defined on: Float32Kind // TypeCheckError: // main/shift_d12.gno:12:12: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d13.gno b/gnovm/tests/files/types/shift_d13.gno index feca282535f..041d82da6fa 100644 --- a/gnovm/tests/files/types/shift_d13.gno +++ b/gnovm/tests/files/types/shift_d13.gno @@ -14,7 +14,7 @@ func main() { } // Error: -// main/shift_d13.gno:13:2: cannot use int as float32 +// main/shift_d13.gno:13:2-22: cannot use int as float32 // TypeCheckError: // main/shift_d13.gno:13:12: cannot use int(1) >> x (value of type int) as float32 value in argument to foo diff --git a/gnovm/tests/files/types/shift_d27.gno b/gnovm/tests/files/types/shift_d27.gno index b3d978d04b5..64e549e1920 100644 --- a/gnovm/tests/files/types/shift_d27.gno +++ b/gnovm/tests/files/types/shift_d27.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/shift_d27.gno:6:2: operator << not defined on: Float32Kind +// main/shift_d27.gno:6:2-15: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_d27.gno:6:8: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d28.gno b/gnovm/tests/files/types/shift_d28.gno index 2f2161398e1..1a2bf7159ba 100644 --- a/gnovm/tests/files/types/shift_d28.gno +++ b/gnovm/tests/files/types/shift_d28.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/shift_d28.gno:6:2: operator << not defined on: Float32Kind +// main/shift_d28.gno:6:2-18: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_d28.gno:6:10: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d32a.gno b/gnovm/tests/files/types/shift_d32a.gno index c86c784ab1a..9bbabf33a15 100644 --- a/gnovm/tests/files/types/shift_d32a.gno +++ b/gnovm/tests/files/types/shift_d32a.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/shift_d32a.gno:7:7: cannot convert untyped bigdec to integer -- 1.2 not an exact integer +// main/shift_d32a.gno:7:7-26: cannot convert untyped bigdec to integer -- 1.2 not an exact integer // TypeCheckError: // main/shift_d32a.gno:7:16: invalid operation: shifted operand 1.2 (untyped float constant) must be integer diff --git a/gnovm/tests/files/types/shift_d34.gno b/gnovm/tests/files/types/shift_d34.gno index bb1785e9cd6..4cacfdb97d9 100644 --- a/gnovm/tests/files/types/shift_d34.gno +++ b/gnovm/tests/files/types/shift_d34.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/shift_d34.gno:7:7: bigint underflows target kind +// main/shift_d34.gno:7:7-29: bigint underflows target kind // TypeCheckError: // main/shift_d34.gno:7:14: -(1 << 2) (untyped int constant -4) overflows uint64 diff --git a/gnovm/tests/files/types/shift_d37.gno b/gnovm/tests/files/types/shift_d37.gno index 8f1e081ba06..d3bde0117f3 100644 --- a/gnovm/tests/files/types/shift_d37.gno +++ b/gnovm/tests/files/types/shift_d37.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_d37.gno:5:10: operator << not defined on: nil +// main/shift_d37.gno:5:10-18: operator << not defined on: nil // TypeCheckError: // main/shift_d37.gno:5:10: invalid operation: shifted operand nil must be integer diff --git a/gnovm/tests/files/types/shift_d38.gno b/gnovm/tests/files/types/shift_d38.gno index fb5a8e7bed9..969e1928a5d 100644 --- a/gnovm/tests/files/types/shift_d38.gno +++ b/gnovm/tests/files/types/shift_d38.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/shift_d38.gno:4:10: cannot convert (const (undefined)) to type uint +// main/shift_d38.gno:4:10-18: cannot convert (const (undefined)) to type uint // TypeCheckError: // main/shift_d38.gno:4:15: cannot convert nil to type uint diff --git a/gnovm/tests/files/types/shift_d4.gno b/gnovm/tests/files/types/shift_d4.gno index 4a2dfbdc0d9..a810e136e45 100644 --- a/gnovm/tests/files/types/shift_d4.gno +++ b/gnovm/tests/files/types/shift_d4.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_d4.gno:4:7: cannot convert BoolKind to Uint64Kind +// main/shift_d4.gno:4:7-27: cannot convert BoolKind to Uint64Kind // TypeCheckError: // main/shift_d4.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type uint64 diff --git a/gnovm/tests/files/types/shift_d40.gno b/gnovm/tests/files/types/shift_d40.gno index 5c870145e34..9a7cb3ce393 100644 --- a/gnovm/tests/files/types/shift_d40.gno +++ b/gnovm/tests/files/types/shift_d40.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d40.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d40.gno:5:7-24: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_d40.gno:5:17: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d41.gno b/gnovm/tests/files/types/shift_d41.gno index 6b093666018..0ffa0ec29ba 100644 --- a/gnovm/tests/files/types/shift_d41.gno +++ b/gnovm/tests/files/types/shift_d41.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d41.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d41.gno:5:7-38: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_d41.gno:5:31: invalid operation: shifted operand 1 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_d44.gno b/gnovm/tests/files/types/shift_d44.gno index 1136a9269dd..5ae88205d38 100644 --- a/gnovm/tests/files/types/shift_d44.gno +++ b/gnovm/tests/files/types/shift_d44.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d44.gno:6:2: operator ++ not defined on: BoolKind +// main/shift_d44.gno:6:2-12: operator ++ not defined on: BoolKind // TypeCheckError: // main/shift_d44.gno:6:2: invalid operation: (a == b)++ (non-numeric type untyped bool) diff --git a/gnovm/tests/files/types/shift_d4a.gno b/gnovm/tests/files/types/shift_d4a.gno index b3a67e6a4fb..c6f29c8afbd 100644 --- a/gnovm/tests/files/types/shift_d4a.gno +++ b/gnovm/tests/files/types/shift_d4a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_d4a.gno:4:7: cannot convert BoolKind to StringKind +// main/shift_d4a.gno:4:7-27: cannot convert BoolKind to StringKind // TypeCheckError: // main/shift_d4a.gno:4:14: cannot convert 1 << 2 == 1 >> 2 (untyped bool constant false) to type string diff --git a/gnovm/tests/files/types/shift_d5.gno b/gnovm/tests/files/types/shift_d5.gno index 55732155c24..8bf17d1d70a 100644 --- a/gnovm/tests/files/types/shift_d5.gno +++ b/gnovm/tests/files/types/shift_d5.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d5.gno:5:2: operator << not defined on: Float64Kind +// main/shift_d5.gno:5:2-15: operator << not defined on: Float64Kind // TypeCheckError: // main/shift_d5.gno:5:7: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_d50.gno b/gnovm/tests/files/types/shift_d50.gno index 4a0875202e9..ab1f16afb7b 100644 --- a/gnovm/tests/files/types/shift_d50.gno +++ b/gnovm/tests/files/types/shift_d50.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/shift_d50.gno:7:7: bigint underflows target kind +// main/shift_d50.gno:7:7-31: bigint underflows target kind // TypeCheckError: // main/shift_d50.gno:7:14: -(1.0 << 2) (untyped int constant -4) overflows uint64 diff --git a/gnovm/tests/files/types/shift_d51.gno b/gnovm/tests/files/types/shift_d51.gno index c144eb1da36..d01477c737f 100644 --- a/gnovm/tests/files/types/shift_d51.gno +++ b/gnovm/tests/files/types/shift_d51.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d51.gno:5:2: operator <<= not defined on: Float64Kind +// main/shift_d51.gno:5:2-9: operator <<= not defined on: Float64Kind // TypeCheckError: // main/shift_d51.gno:5:2: invalid operation: shifted operand a (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_d54.gno b/gnovm/tests/files/types/shift_d54.gno index 3a541e30337..5964a5d3261 100644 --- a/gnovm/tests/files/types/shift_d54.gno +++ b/gnovm/tests/files/types/shift_d54.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/shift_d54.gno:8:7: invalid operation: b + a << (const (2 uint)) (mismatched types int32 and int) +// main/shift_d54.gno:8:7-15: invalid operation: b + a << (const (2 uint)) (mismatched types int32 and int) // TypeCheckError: // main/shift_d54.gno:8:7: invalid operation: b + a << 2 (mismatched types int32 and int) diff --git a/gnovm/tests/files/types/shift_d56.gno b/gnovm/tests/files/types/shift_d56.gno index 08224bbcdbc..000a9670b49 100644 --- a/gnovm/tests/files/types/shift_d56.gno +++ b/gnovm/tests/files/types/shift_d56.gno @@ -13,7 +13,7 @@ func main() { } // Error: -// main/shift_d56.gno:6:2: cannot use int as int64 +// main/shift_d56.gno:6:2-22: cannot use int as int64 // TypeCheckError: // main/shift_d56.gno:6:9: cannot use 1 << 4 + int(1) (constant 17 of type int) as int64 value in return statement diff --git a/gnovm/tests/files/types/shift_d5b.gno b/gnovm/tests/files/types/shift_d5b.gno index c3d8dcd7370..d8464adfc10 100644 --- a/gnovm/tests/files/types/shift_d5b.gno +++ b/gnovm/tests/files/types/shift_d5b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_d5b.gno:5:7: operator << not defined on: Float32Kind +// main/shift_d5b.gno:5:7-24: operator << not defined on: Float32Kind // TypeCheckError: // main/shift_d5b.gno:5:15: invalid operation: shifted operand 1.0 (type float32) must be integer diff --git a/gnovm/tests/files/types/shift_e0.gno b/gnovm/tests/files/types/shift_e0.gno index 71b0bc6bd35..06d395ae1cb 100644 --- a/gnovm/tests/files/types/shift_e0.gno +++ b/gnovm/tests/files/types/shift_e0.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/shift_e0.gno:4:10: invalid operation: negative shift count: (const (-1 bigint)) +// main/shift_e0.gno:4:10-17: invalid operation: negative shift count: (const (-1 bigint)) // TypeCheckError: // main/shift_e0.gno:4:15: invalid operation: negative shift count -1 (untyped int constant) diff --git a/gnovm/tests/files/types/shift_e1.gno b/gnovm/tests/files/types/shift_e1.gno index 7246dd5b9de..6b00c628a7a 100644 --- a/gnovm/tests/files/types/shift_e1.gno +++ b/gnovm/tests/files/types/shift_e1.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/shift_e1.gno:4:10: invalid operation: invalid shift count: (const (2.5848584 float32)) +// main/shift_e1.gno:4:10-36: invalid operation: invalid shift count: (const (2.5848584 float32)) // TypeCheckError: // main/shift_e1.gno:4:17: invalid operation: invalid shift count float32(2.58485848) (constant 2.58486 of type float32) diff --git a/gnovm/tests/files/types/shift_e2.gno b/gnovm/tests/files/types/shift_e2.gno index da7b6ef7d59..6908d8ffa08 100644 --- a/gnovm/tests/files/types/shift_e2.gno +++ b/gnovm/tests/files/types/shift_e2.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/shift_e2.gno:4:10: invalid operation: invalid shift count: (const (1.25 bigdec)) +// main/shift_e2.gno:4:10-19: invalid operation: invalid shift count: (const (1.25 bigdec)) // TypeCheckError: // main/shift_e2.gno:4:15: 1.25 (untyped float constant) truncated to uint diff --git a/gnovm/tests/files/types/shift_e3.gno b/gnovm/tests/files/types/shift_e3.gno index 1d6048bc9c3..9fb547f70a4 100644 --- a/gnovm/tests/files/types/shift_e3.gno +++ b/gnovm/tests/files/types/shift_e3.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_e3.gno:5:10: invalid operation: invalid shift count: x +// main/shift_e3.gno:5:10-16: invalid operation: invalid shift count: x // TypeCheckError: // main/shift_e3.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e4.gno b/gnovm/tests/files/types/shift_e4.gno index 05c20a6ed23..5c568463efb 100644 --- a/gnovm/tests/files/types/shift_e4.gno +++ b/gnovm/tests/files/types/shift_e4.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_e4.gno:5:10: invalid operation: invalid shift count: x +// main/shift_e4.gno:5:10-16: invalid operation: invalid shift count: x // TypeCheckError: // main/shift_e4.gno:5:15: invalid operation: shift count x (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e7.gno b/gnovm/tests/files/types/shift_e7.gno index 360e6c8fd9e..d9e1a9d8535 100644 --- a/gnovm/tests/files/types/shift_e7.gno +++ b/gnovm/tests/files/types/shift_e7.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_e7.gno:5:2: invalid operation: negative shift count: (-1 bigint) +// main/shift_e7.gno:5:2-10: invalid operation: negative shift count: (-1 bigint) // TypeCheckError: // main/shift_e7.gno:5:8: invalid operation: negative shift count -1 (untyped int constant) diff --git a/gnovm/tests/files/types/shift_e7a.gno b/gnovm/tests/files/types/shift_e7a.gno index 8cdd455f8fc..09c1982c5a5 100644 --- a/gnovm/tests/files/types/shift_e7a.gno +++ b/gnovm/tests/files/types/shift_e7a.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_e7a.gno:5:10: invalid operation: invalid shift count: a +// main/shift_e7a.gno:5:10-16: invalid operation: invalid shift count: a // TypeCheckError: // main/shift_e7a.gno:5:15: invalid operation: shift count a (variable of type float64) must be integer diff --git a/gnovm/tests/files/types/shift_e7b.gno b/gnovm/tests/files/types/shift_e7b.gno index 6fed70c69f9..1e60bbfc0f3 100644 --- a/gnovm/tests/files/types/shift_e7b.gno +++ b/gnovm/tests/files/types/shift_e7b.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/shift_e7b.gno:4:10: invalid operation: invalid shift count: (const (-1 float64)) +// main/shift_e7b.gno:4:10-26: invalid operation: invalid shift count: (const (-1 float64)) // TypeCheckError: // main/shift_e7b.gno:4:15: invalid operation: negative shift count float64(-1) (constant -1 of type float64) diff --git a/gnovm/tests/files/types/shift_e8.gno b/gnovm/tests/files/types/shift_e8.gno index 859613a1d54..2dd1a6758d9 100644 --- a/gnovm/tests/files/types/shift_e8.gno +++ b/gnovm/tests/files/types/shift_e8.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/shift_e8.gno:5:2: invalid operation: invalid shift count: (const (1.25 bigdec)) +// main/shift_e8.gno:5:2-12: invalid operation: invalid shift count: (const (1.25 bigdec)) // TypeCheckError: // main/shift_e8.gno:5:8: 1.25 (untyped float constant) truncated to uint diff --git a/gnovm/tests/files/types/shift_f1b.gno b/gnovm/tests/files/types/shift_f1b.gno index 2ec54e4dc94..2c3fe838cd4 100644 --- a/gnovm/tests/files/types/shift_f1b.gno +++ b/gnovm/tests/files/types/shift_f1b.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/shift_f1b.gno:7:2: operator << not defined on: BigdecKind +// main/shift_f1b.gno:7:2-18: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f1b.gno:7:7: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2.gno b/gnovm/tests/files/types/shift_f2.gno index a1b4955f996..c545eeea52d 100644 --- a/gnovm/tests/files/types/shift_f2.gno +++ b/gnovm/tests/files/types/shift_f2.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f2.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2.gno:5:6-22: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f2.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2a.gno b/gnovm/tests/files/types/shift_f2a.gno index 93f2e5cc953..105d63eefa9 100644 --- a/gnovm/tests/files/types/shift_f2a.gno +++ b/gnovm/tests/files/types/shift_f2a.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f2a.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2a.gno:5:6-22: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f2a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2b.gno b/gnovm/tests/files/types/shift_f2b.gno index a6b33f098c1..6ab15b20bc0 100644 --- a/gnovm/tests/files/types/shift_f2b.gno +++ b/gnovm/tests/files/types/shift_f2b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f2b.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2b.gno:5:6-22: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f2b.gno:5:18: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2c.gno b/gnovm/tests/files/types/shift_f2c.gno index 3566824c613..b8740030739 100644 --- a/gnovm/tests/files/types/shift_f2c.gno +++ b/gnovm/tests/files/types/shift_f2c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f2c.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f2c.gno:5:6-22: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f2c.gno:5:16: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f2d.gno b/gnovm/tests/files/types/shift_f2d.gno index a5721b3ce64..e4fa8e2ef5e 100644 --- a/gnovm/tests/files/types/shift_f2d.gno +++ b/gnovm/tests/files/types/shift_f2d.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f2d.gno:5:11: incompatible types in binary expression: bigint NEQ bigdec +// main/shift_f2d.gno:5:11-25: incompatible types in binary expression: bigint NEQ bigdec // TypeCheckError: // main/shift_f2d.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer; main/shift_f2d.gno:5:19: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3.gno b/gnovm/tests/files/types/shift_f3.gno index ff949765250..617e6588a1d 100644 --- a/gnovm/tests/files/types/shift_f3.gno +++ b/gnovm/tests/files/types/shift_f3.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f3.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3.gno:5:6-21: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f3.gno:5:11: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3a.gno b/gnovm/tests/files/types/shift_f3a.gno index 5fd159536dc..f46956fd1bb 100644 --- a/gnovm/tests/files/types/shift_f3a.gno +++ b/gnovm/tests/files/types/shift_f3a.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f3a.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3a.gno:5:6-21: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f3a.gno:5:11: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3b.gno b/gnovm/tests/files/types/shift_f3b.gno index 1a914c8ab75..b5d69bb4fc8 100644 --- a/gnovm/tests/files/types/shift_f3b.gno +++ b/gnovm/tests/files/types/shift_f3b.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f3b.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3b.gno:5:6-21: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f3b.gno:5:17: invalid operation: shifted operand 1 (type float64) must be integer diff --git a/gnovm/tests/files/types/shift_f3c.gno b/gnovm/tests/files/types/shift_f3c.gno index cce2059d28e..13413ef8cad 100644 --- a/gnovm/tests/files/types/shift_f3c.gno +++ b/gnovm/tests/files/types/shift_f3c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/shift_f3c.gno:5:6: operator << not defined on: BigdecKind +// main/shift_f3c.gno:5:6-21: operator << not defined on: BigdecKind // TypeCheckError: // main/shift_f3c.gno:5:15: invalid operation: shifted operand 1.0 (type float64) must be integer diff --git a/gnovm/tests/files/types/typed_nil_a.gno b/gnovm/tests/files/types/typed_nil_a.gno index 494b2741480..d5434aa3bc4 100644 --- a/gnovm/tests/files/types/typed_nil_a.gno +++ b/gnovm/tests/files/types/typed_nil_a.gno @@ -15,7 +15,7 @@ func main() { } // Error: -// main/typed_nil_a.gno:10:5: cannot convert (const (undefined)) to IntKind +// main/typed_nil_a.gno:10:5-17: cannot convert (const (undefined)) to IntKind // TypeCheckError: // main/typed_nil_a.gno:10:13: cannot convert nil to type integer diff --git a/gnovm/tests/files/types/unary_a0c.gno b/gnovm/tests/files/types/unary_a0c.gno index 9edb1a51de5..3e700f12328 100644 --- a/gnovm/tests/files/types/unary_a0c.gno +++ b/gnovm/tests/files/types/unary_a0c.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/unary_a0c.gno:7:7: operator + not defined on: StringKind +// main/unary_a0c.gno:7:7-9: operator + not defined on: StringKind // TypeCheckError: // main/unary_a0c.gno:7:8: invalid operation: operator + not defined on x (variable of type string) diff --git a/gnovm/tests/files/types/unary_a2a.gno b/gnovm/tests/files/types/unary_a2a.gno index adc45057a69..7dc75470a48 100644 --- a/gnovm/tests/files/types/unary_a2a.gno +++ b/gnovm/tests/files/types/unary_a2a.gno @@ -10,7 +10,7 @@ func main() { } // Error: -// main/unary_a2a.gno:7:7: operator ! not defined on: IntKind +// main/unary_a2a.gno:7:7-9: operator ! not defined on: IntKind // TypeCheckError: // main/unary_a2a.gno:7:8: invalid operation: operator ! not defined on a (variable of type int) diff --git a/gnovm/tests/files/types/unary_a6.gno b/gnovm/tests/files/types/unary_a6.gno index 8c1c608e9b6..f143c563535 100644 --- a/gnovm/tests/files/types/unary_a6.gno +++ b/gnovm/tests/files/types/unary_a6.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/unary_a6.gno:7:7: operator ^ not defined on: Float64Kind +// main/unary_a6.gno:7:7-9: operator ^ not defined on: Float64Kind // TypeCheckError: // main/unary_a6.gno:7:8: invalid operation: operator ^ not defined on x (variable of type float64) diff --git a/gnovm/tests/files/var18.gno b/gnovm/tests/files/var18.gno index 75f5143b742..2036f0f9d90 100644 --- a/gnovm/tests/files/var18.gno +++ b/gnovm/tests/files/var18.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/var18.gno:4:6: missing init expr for c +// main/var18.gno:4:6-20: missing init expr for c // TypeCheckError: // main/var18.gno:4:12: missing init expr for c; main/var18.gno:4:6: declared and not used: a; main/var18.gno:4:9: declared and not used: b; main/var18.gno:4:12: declared and not used: c diff --git a/gnovm/tests/files/var19.gno b/gnovm/tests/files/var19.gno index 6d632326b56..e8968f8a79c 100644 --- a/gnovm/tests/files/var19.gno +++ b/gnovm/tests/files/var19.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/var19.gno:4:6: missing init expr for c +// main/var19.gno:4:6-24: missing init expr for c // TypeCheckError: // main/var19.gno:4:12: missing init expr for c; main/var19.gno:4:19: undefined: a diff --git a/gnovm/tests/files/var20.gno b/gnovm/tests/files/var20.gno index ea9743889dd..31ebeda7ba9 100644 --- a/gnovm/tests/files/var20.gno +++ b/gnovm/tests/files/var20.gno @@ -9,7 +9,7 @@ func main() { } // Error: -// main/var20.gno:8:6: assignment mismatch: 3 variable(s) but r() returns 1 value(s) +// main/var20.gno:8:6-19: assignment mismatch: 3 variable(s) but r() returns 1 value(s) // TypeCheckError: // main/var20.gno:8:16: assignment mismatch: 3 variables but r returns 1 value; main/var20.gno:8:6: declared and not used: a; main/var20.gno:8:9: declared and not used: b; main/var20.gno:8:12: declared and not used: c diff --git a/gnovm/tests/files/var21.gno b/gnovm/tests/files/var21.gno index cd07ed99020..d7f31d666ba 100644 --- a/gnovm/tests/files/var21.gno +++ b/gnovm/tests/files/var21.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/var21.gno:8:6: multiple-value foo (value of type [int bool]) in single-value context +// main/var21.gno:8:6-21: multiple-value foo (value of type [int bool]) in single-value context // TypeCheckError: // main/var21.gno:8:16: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/var22.gno b/gnovm/tests/files/var22.gno index 86923221c0e..ddeec11d9e4 100644 --- a/gnovm/tests/files/var22.gno +++ b/gnovm/tests/files/var22.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/var22.gno:8:6: missing init expr for c +// main/var22.gno:8:6-24: missing init expr for c // TypeCheckError: // main/var22.gno:8:12: missing init expr for c; main/var22.gno:8:19: multiple-value foo() (value of type (int, bool)) in single-value context diff --git a/gnovm/tests/files/var22b.gno b/gnovm/tests/files/var22b.gno index aeea596973b..965738320e6 100644 --- a/gnovm/tests/files/var22b.gno +++ b/gnovm/tests/files/var22b.gno @@ -11,7 +11,7 @@ func main() { } // Error: -// main/var22b.gno:8:6: extra init expr foo() +// main/var22b.gno:8:6-30: extra init expr foo() // TypeCheckError: // main/var22b.gno:8:25: extra init expr foo() diff --git a/gnovm/tests/files/var22c.gno b/gnovm/tests/files/var22c.gno index ff31963e8d7..6eaeb907d4e 100644 --- a/gnovm/tests/files/var22c.gno +++ b/gnovm/tests/files/var22c.gno @@ -12,7 +12,7 @@ func main() { } // Error: -// main/var22c.gno:10:6: missing init expr for z +// main/var22c.gno:10:6-22: missing init expr for z // TypeCheckError: // main/var22c.gno:10:12: missing init expr for z; main/var22c.gno:10:19: multiple-value f() (value of type (a int, b int)) in single-value context diff --git a/gnovm/tests/files/var23.gno b/gnovm/tests/files/var23.gno index 02c2a9be9ef..057ece3371d 100644 --- a/gnovm/tests/files/var23.gno +++ b/gnovm/tests/files/var23.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/var23.gno:3:5: assignment mismatch: 3 variable(s) but 2 value(s) +// main/var23.gno:3:5-19: assignment mismatch: 3 variable(s) but 2 value(s) // TypeCheckError: // main/var23.gno:3:11: missing init expr for c diff --git a/gnovm/tests/files/var24.gno b/gnovm/tests/files/var24.gno index 92c2c677323..5d4489eddc4 100644 --- a/gnovm/tests/files/var24.gno +++ b/gnovm/tests/files/var24.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/var24.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) +// main/var24.gno:5:6-23: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: // main/var24.gno:5:16: assignment mismatch: 3 variables but 1 value; main/var24.gno:5:6: declared and not used: a; main/var24.gno:5:9: declared and not used: b; main/var24.gno:5:12: declared and not used: c diff --git a/gnovm/tests/files/var25.gno b/gnovm/tests/files/var25.gno index 8bb56589a51..73055e94035 100644 --- a/gnovm/tests/files/var25.gno +++ b/gnovm/tests/files/var25.gno @@ -6,7 +6,7 @@ func main() { } // Error: -// main/var25.gno:5:6: assignment mismatch: 3 variable(s) but 1 value(s) +// main/var25.gno:5:6-20: assignment mismatch: 3 variable(s) but 1 value(s) // TypeCheckError: // main/var25.gno:5:16: assignment mismatch: 3 variables but 1 value; main/var25.gno:5:6: declared and not used: a; main/var25.gno:5:9: declared and not used: b; main/var25.gno:5:12: declared and not used: c diff --git a/gnovm/tests/files/var26.gno b/gnovm/tests/files/var26.gno index fcbeff3027d..fec573384a0 100644 --- a/gnovm/tests/files/var26.gno +++ b/gnovm/tests/files/var26.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/var26.gno:6:6: extra init expr 3 +// main/var26.gno:6:6-20: extra init expr 3 // TypeCheckError: // main/var26.gno:6:19: extra init expr 3 diff --git a/gnovm/tests/files/var31.gno b/gnovm/tests/files/var31.gno index db5f1c0aa46..0e7d3454cb1 100644 --- a/gnovm/tests/files/var31.gno +++ b/gnovm/tests/files/var31.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/var31.gno:4:6: struct{} (type) is not an expression +// main/var31.gno:4:6-18: struct{} (type) is not an expression // TypeCheckError: // main/var31.gno:4:10: struct{} (type) is not an expression; main/var31.gno:4:6: declared and not used: t diff --git a/gnovm/tests/files/var32.gno b/gnovm/tests/files/var32.gno index 196be88d48a..4f622c25735 100644 --- a/gnovm/tests/files/var32.gno +++ b/gnovm/tests/files/var32.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/var32.gno:4:6: use of untyped nil in variable declaration +// main/var32.gno:4:6-13: use of untyped nil in variable declaration // TypeCheckError: // main/var32.gno:4:10: use of untyped nil in variable declaration; main/var32.gno:4:6: declared and not used: t diff --git a/gnovm/tests/files/var34.gno b/gnovm/tests/files/var34.gno index 1bd82630473..c69881cfb2c 100644 --- a/gnovm/tests/files/var34.gno +++ b/gnovm/tests/files/var34.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/var34.gno:6:6: f (no value) used as value +// main/var34.gno:6:6-13: f (no value) used as value // TypeCheckError: // main/var34.gno:6:10: f() (no value) used as value; main/var34.gno:6:6: declared and not used: t diff --git a/gnovm/tests/files/var34b.gno b/gnovm/tests/files/var34b.gno index cfe47823865..b7ddb487a48 100644 --- a/gnovm/tests/files/var34b.gno +++ b/gnovm/tests/files/var34b.gno @@ -8,7 +8,7 @@ func main() { } // Error: -// main/var34b.gno:7:2: f (no value) used as value +// main/var34b.gno:7:2-9: f (no value) used as value // TypeCheckError: // main/var34b.gno:7:6: f() (no value) used as value; main/var34b.gno:6:6: declared and not used: a diff --git a/gnovm/tests/files/var34c.gno b/gnovm/tests/files/var34c.gno index 5491d74a6a4..fc01fcc90c7 100644 --- a/gnovm/tests/files/var34c.gno +++ b/gnovm/tests/files/var34c.gno @@ -7,7 +7,7 @@ func main() { } // Error: -// main/var34c.gno:6:6: f (no value) used as value +// main/var34c.gno:6:6-23: f (no value) used as value // TypeCheckError: // main/var34c.gno:6:17: f() (no value) used as value; main/var34c.gno:6:6: declared and not used: a; main/var34c.gno:6:9: declared and not used: b diff --git a/gnovm/tests/files/var35.gno b/gnovm/tests/files/var35.gno index c91057dfe24..68ff04034ed 100644 --- a/gnovm/tests/files/var35.gno +++ b/gnovm/tests/files/var35.gno @@ -5,7 +5,7 @@ func main() { } // Error: -// main/var35.gno:4:6: cannot use nil as int value in variable declaration +// main/var35.gno:4:6-17: cannot use nil as int value in variable declaration // TypeCheckError: // main/var35.gno:4:14: cannot use nil as int value in variable declaration; main/var35.gno:4:6: declared and not used: i From ce758b8782bd2336c2a905b0b229726239c835d2 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 19 May 2025 01:26:55 -0700 Subject: [PATCH 38/83] replaceWithDirPath -> guessFilePathLoc; reParseRecover works with Span --- gnovm/cmd/gno/common.go | 95 ++++++++++++++++++--------- gnovm/cmd/gno/run.go | 15 +++-- gnovm/pkg/gnolang/gnomod.go | 11 ++-- gnovm/pkg/gnolang/gotypecheck.go | 1 + gnovm/pkg/gnolang/transpile_gno0p9.go | 8 ++- gnovm/pkg/test/imports.go | 4 ++ 6 files changed, 88 insertions(+), 46 deletions(-) diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index ea2f8a0c319..fb8339b843f 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -82,29 +82,16 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( return } -func guessSourcePath(pkgPath, fname string) string { - if info, err := os.Stat(pkgPath); !os.IsNotExist(err) && !info.IsDir() { - pkgPath = filepath.Dir(pkgPath) - } - - fnameJoin := filepath.Join(pkgPath, fname) - if _, err := os.Stat(fnameJoin); !os.IsNotExist(err) { - return filepath.Clean(fnameJoin) - } - - if _, err := os.Stat(fname); !os.IsNotExist(err) { - return filepath.Clean(fname) - } - - return filepath.Clean(pkgPath) -} - // reParseRecover is a regex designed to parse error details from a string. // It extracts the file location, line number, and error message from a // formatted error string. // XXX: Ideally, error handling should encapsulate location details within a // dedicated error type. -var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) +const rePos = `(?:` + `\d+(?::\d+)?` + `)` // NOTE: allows the omission of columns, more relaxed than gno.Pos. +const reSpan = `(?:` + rePos + `-` + rePos + `)` +const rePosOrSpan = `(?:` + reSpan + `|` + rePos + `)` + +var reParseRecover = regexp.MustCompile(`^([^:]+):(` + rePosOrSpan + `):? *(.*)$`) func printError(w io.WriteCloser, dir, pkgPath string, err error) { switch err := err.(type) { @@ -129,7 +116,7 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { }) case types.Error: loc := err.Fset.Position(err.Pos).String() - loc = replaceWithDirPath(loc, pkgPath, dir) + loc = guessFilePathLoc(loc, pkgPath, dir) code := gnoTypeCheckError if strings.Contains(err.Msg, "(unknown import path \"") { // NOTE: This is a bit of a hack. @@ -146,7 +133,7 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { case scanner.ErrorList: for _, err := range err { loc := err.Pos.String() - loc = replaceWithDirPath(loc, pkgPath, dir) + loc = guessFilePathLoc(loc, pkgPath, dir) fmt.Fprintln(w, gnoIssue{ Code: gnoParserError, Msg: err.Msg, @@ -156,7 +143,7 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { } case scanner.Error: loc := err.Pos.String() - loc = replaceWithDirPath(loc, pkgPath, dir) + loc = guessFilePathLoc(loc, pkgPath, dir) fmt.Fprintln(w, gnoIssue{ Code: gnoParserError, Msg: err.Msg, @@ -206,14 +193,16 @@ func guessIssueFromError(dir, pkgPath string, err error, code gnoCode) gnoIssue issue.Code = code parsedError := strings.TrimSpace(err.Error()) - parsedError = replaceWithDirPath(parsedError, pkgPath, dir) - parsedError = strings.TrimPrefix(parsedError, pkgPath+"/") - matches := reParseRecover.FindStringSubmatch(parsedError) + if len(matches) > 0 { - sourcepath := guessSourcePath(pkgPath, matches[1]) - issue.Location = sourcepath + matches[2] - issue.Msg = strings.TrimSpace(matches[3]) + errPath := matches[1] + errLoc := matches[2] + errMsg := matches[3] + errPath = guessFilePathLoc(errPath, pkgPath, dir) + errPath = filepath.Clean(errPath) + issue.Location = errPath + ":" + errLoc + issue.Msg = strings.TrimSpace(errMsg) } else { issue.Location = fmt.Sprintf("%s:0", filepath.Clean(pkgPath)) issue.Msg = err.Error() @@ -221,9 +210,55 @@ func guessIssueFromError(dir, pkgPath string, err error, code gnoCode) gnoIssue return issue } -func replaceWithDirPath(s, pkgPath, dir string) string { - if strings.HasPrefix(s, pkgPath) { - return filepath.Clean(dir + s[len(pkgPath):]) +// Takes a location string `s` and tries to convert to a path based on `dir`. +// NOTE: s may not be in pkgPath (e.g. for type-check errors on imports). +// Do not make a transformation unless the answer is highly unlikely to be incorrect. +// Otherwise debugging may be painful. Better to return s as is. +func guessFilePathLoc(s, pkgPath, dir string) string { + if !dirExists(dir) { + panic(fmt.Sprintf("dir %q does not exist", dir)) } + s = filepath.Clean(s) + pkgPath = filepath.Clean(pkgPath) + dir = filepath.Clean(dir) + // s already in dir. + if strings.HasPrefix(s, dir) { + return s + } + // s in pkgPath. + if strings.HasPrefix(s, pkgPath+"/") { + fname := s[len(pkgPath+"/"):] + fpath := filepath.Join(dir, fname) + return fpath + } + // "GNOROOT". + if strings.HasSuffix(dir, pkgPath) { + gnoRoot := dir[len(dir)-len(pkgPath):] + // s is maybe / + if strings.Contains(s, "/") { + fpath := gnoRoot + s + if fileExists(fpath) { + return fpath + } + } + } + // s is a filename. + if !strings.Contains(s, "/") { + fpath := filepath.Join(dir, s) + if fileExists(fpath) { + return fpath + } + } + // dunno. return s } + +func dirExists(dir string) bool { + info, err := os.Stat(dir) + return !os.IsNotExist(err) && info.IsDir() +} + +func fileExists(fpath string) bool { + info, err := os.Stat(fpath) + return !os.IsNotExist(err) && !info.IsDir() +} diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index 9fa5a7ef5a6..bde398586e6 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -136,12 +136,12 @@ func execRun(cfg *runCfg, args []string, io commands.IO) error { return runExpr(m, cfg.expr) } -func parseFiles(fnames []string, stderr io.WriteCloser) ([]*gno.FileNode, error) { - files := make([]*gno.FileNode, 0, len(fnames)) +func parseFiles(fpaths []string, stderr io.WriteCloser) ([]*gno.FileNode, error) { + files := make([]*gno.FileNode, 0, len(fpaths)) var didPanic bool - for _, fname := range fnames { - if s, err := os.Stat(fname); err == nil && s.IsDir() { - subFns, err := listNonTestFiles(fname) + for _, fpath := range fpaths { + if s, err := os.Stat(fpath); err == nil && s.IsDir() { + subFns, err := listNonTestFiles(fpath) if err != nil { return nil, err } @@ -157,8 +157,9 @@ func parseFiles(fnames []string, stderr io.WriteCloser) ([]*gno.FileNode, error) return nil, err } - didPanic = catchPanic(fname, fname, stderr, func() { - files = append(files, gno.MustReadFile(fname)) + dir, fname := filepath.Split(fpath) + didPanic = catchPanic(dir, fname, stderr, func() { + files = append(files, gno.MustReadFile(fpath)) }) } diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index e8e49fe6d4d..c8f4d53ed25 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -41,13 +41,13 @@ func genGnoMod(pkgPath string, gnoVersion string) string { const ( GnoVerLatest = `0.9` // current version GnoVerTesting = `0.9` // version of our tests - GnoVerDefault = `0.9` // no gno.mod + GnoVerDefault = `0.9` // auto generated gno.mod + GnoVerMissing = `0.0` // missing gno.mod, !autoGnoMod XXX ) // ======================================== // Parses and checks the gno.mod file from mpkg. -// To generate default ones, use: -// gnomod.ParseBytes(GnoModDefault) +// To generate default ones, GenGnoMod*(). // // Results: // - mod: the gno.mod file, or nil if not found. @@ -64,9 +64,8 @@ func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { // error parsing gno.mod. err = fmt.Errorf("%s/gno.mod: parse error %q", mpkg.Path, err) } else if mod.Gno == nil { - // 'gno 0.9' was never specified; just write 0.0. - mod.SetGno(GnoVerDefault) - // err = fmt.Errorf("%s/gno.mod: gno version unspecified", mpkg.Path) + // gno.mod was never specified; set missing. + mod.SetGno(GnoVerMissing) } else if mod.Gno.Version == GnoVersion { // current version, nothing to do. } else { diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 434b3c817ac..427a985fe97 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -17,6 +17,7 @@ import ( /* Type-checking (using go/types). Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). + XXX move to pkg/gnolang/importer.go. */ // MemPackageGetter implements the GetMemPackage() method. It is a subset of diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 389ff06def6..292acaaf81e 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -484,9 +484,11 @@ XFORMS1_LOOP: } panic("xforms1 and xforms2 don't match") } - if len(xforms1) != len(xforms2) { - panic("xforms1 and xforms2 length don't match") - } + /* + if len(xforms1) != len(xforms2) { + panic("xforms1 and xforms2 length don't match") + } + */ return found // good } diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 96c99dccd65..8e00f0eb3e4 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -30,6 +30,10 @@ type StoreOptions struct { // [gno.Machine.PreprocessFiles]. It avoids executing code for contexts // which only intend to perform a type check, ie. `gno lint`. PreprocessOnly bool + + // When transpiling code in examples/ we use the test store. gno fix may need + // gno.mod to not be auto-generated when importing from the test store. + DoNotGenerateGnoMod bool } // NOTE: this isn't safe, should only be used for testing. From 1184e225cff3e02b49eaad1621699af84ef2f89c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Mon, 19 May 2025 16:16:26 -0700 Subject: [PATCH 39/83] don't skip preprocessing for funclitexpr inside a func decl --- gnovm/pkg/gnolang/preprocess.go | 5 ++++- gnovm/tests/files/funclit0.gno | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 gnovm/tests/files/funclit0.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 70966c056c8..c764ad07bbc 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -4014,7 +4014,10 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin if un != "" { return } - cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + switch last.(type) { + case *PackageNode, *FileNode: + cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + } case *FieldTypeExpr: // FIELD return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) case *ArrayTypeExpr: diff --git a/gnovm/tests/files/funclit0.gno b/gnovm/tests/files/funclit0.gno new file mode 100644 index 00000000000..11173bb4a29 --- /dev/null +++ b/gnovm/tests/files/funclit0.gno @@ -0,0 +1,18 @@ +package main + +// This tests an issue where the preprocessor was failing after +// implementing ATTR_PREPROCESS_SKIPPED. + +func main() { + var myDep1 string = "hello" + + var myVar1 = func() { + a := myDep1 + println(a) + } + + myVar1() +} + +// Output: +// hello From 36f4f3927abd246d9cccbc16a35f28ff8edf3ba5 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 14:04:51 +0300 Subject: [PATCH 40/83] add two funclit tests --- gnovm/tests/files/funclit1.gno | 27 +++++++++++++++++++++++++++ gnovm/tests/files/funclit2.gno | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 gnovm/tests/files/funclit1.gno create mode 100644 gnovm/tests/files/funclit2.gno diff --git a/gnovm/tests/files/funclit1.gno b/gnovm/tests/files/funclit1.gno new file mode 100644 index 00000000000..9547dc7b671 --- /dev/null +++ b/gnovm/tests/files/funclit1.gno @@ -0,0 +1,27 @@ +package main + +// This tests an issue where the preprocessor was failing after +// implementing ATTR_PREPROCESS_SKIPPED. + +var myVar0 = func() { + var myDep1 string = "hello" + + var myVar1 = func() { + a := myDep1 + println(a) + } + myVar1() + + println(myDep0) +} + +var myDep0 string = "world" + +func main() { + + myVar0() +} + +// Output: +// hello +// world diff --git a/gnovm/tests/files/funclit2.gno b/gnovm/tests/files/funclit2.gno new file mode 100644 index 00000000000..31968e01ab3 --- /dev/null +++ b/gnovm/tests/files/funclit2.gno @@ -0,0 +1,32 @@ +package main + +// This tests an issue where the preprocessor was failing after +// implementing ATTR_PREPROCESS_SKIPPED. + +var myVar0 = func() { + + var myVar1 = func() { + a := myDep1 + println(a) + } + + // invalid + var myDep1 string = "hello" + + myVar1() + + println(myDep0) +} + +var myDep0 string = "world" + +func main() { + + myVar0() +} + +// Error: +// main/funclit2.gno:9:8-14: name myDep1 not declared + +// TypeCheckError: +// main/funclit2.gno:9:8: undefined: myDep1; main/funclit2.gno:14:6: declared and not used: myDep1 From 6dce3666a0f14a936f28f274368cbdcbe4937875 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 17:08:18 +0300 Subject: [PATCH 41/83] check parent blocknode to ensure correct skip for funcLit --- gnovm/pkg/gnolang/preprocess.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c764ad07bbc..11700ae6448 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -4014,10 +4014,17 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin if un != "" { return } - switch last.(type) { - case *PackageNode, *FileNode: - cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + // only skip when no outer funcDecl or funcLit + for last != nil { + switch last.(type) { + case *FuncDecl, *FuncLitExpr: + return + } + last = last.GetParentNode(nil) } + + cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + case *FieldTypeExpr: // FIELD return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) case *ArrayTypeExpr: From 1ed62d7e875de92b9fe980198bd76b66966b479d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:20:55 +0300 Subject: [PATCH 42/83] fix grc20 --- examples/gno.land/p/demo/grc/grc20/token_test.gno | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/p/demo/grc/grc20/token_test.gno b/examples/gno.land/p/demo/grc/grc20/token_test.gno index 8bd1f4b3c61..d526727722c 100644 --- a/examples/gno.land/p/demo/grc/grc20/token_test.gno +++ b/examples/gno.land/p/demo/grc/grc20/token_test.gno @@ -95,9 +95,8 @@ func TestMintOverflow(t *testing.T) { func TestTransferFromAtomicity(t *testing.T) { var ( - owner = testutils.TestAddress("owner") - spender = testutils.TestAddress("spender") - recipient = testutils.TestAddress("recipient") + owner = testutils.TestAddress("owner") + spender = testutils.TestAddress("spender") invalidRecipient = std.Address("") ) From 3bac84adef28c2b37176d4a97c352933ea677e6e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:23:25 +0300 Subject: [PATCH 43/83] fix p/moul/collection --- .../gno.land/p/moul/collection/collection_test.gno | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/p/moul/collection/collection_test.gno b/examples/gno.land/p/moul/collection/collection_test.gno index ea2e493df3f..8c191492f14 100644 --- a/examples/gno.land/p/moul/collection/collection_test.gno +++ b/examples/gno.land/p/moul/collection/collection_test.gno @@ -131,7 +131,7 @@ func TestUpdates(t *testing.T) { p2 := &Person{Name: "Bob", Username: "bob456"} id1 := c.Set(p1) - id2 := c.Set(p2) + c.Set(p2) tests := []struct { name string @@ -254,7 +254,7 @@ func TestEdgeCases(t *testing.T) { if entry == nil { return false } - id, err := seqid.FromString(entry.ID) + _, err := seqid.FromString(entry.ID) if err != nil { return false } @@ -330,7 +330,7 @@ func TestIndexOptions(t *testing.T) { return v.(*Person).Username }, UniqueIndex) - id1 := c.Set(&Person{Username: "Alice"}) + c.Set(&Person{Username: "Alice"}) return c.Set(&Person{Username: "Alice"}) // Should fail }, wantID: false, @@ -342,7 +342,7 @@ func TestIndexOptions(t *testing.T) { return v.(*Person).Email }, UniqueIndex|CaseInsensitiveIndex) - id1 := c.Set(&Person{Email: "test@example.com"}) + c.Set(&Person{Email: "test@example.com"}) return c.Set(&Person{Email: "TEST@EXAMPLE.COM"}) // Should fail }, wantID: false, @@ -372,7 +372,7 @@ func TestIndexOptions(t *testing.T) { return v.(*Person).Name }, UniqueIndex|CaseInsensitiveIndex|SparseIndex) - id1 := c.Set(&Person{Name: "Alice"}) + c.Set(&Person{Name: "Alice"}) return c.Set(&Person{Name: "ALICE"}) // Should fail }, wantID: false, From 6b39db067b42eea75306a46d0f07ee6a83c9d49c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:25:04 +0300 Subject: [PATCH 44/83] fix p/moul/txlink --- examples/gno.land/p/moul/txlink/txlink.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/p/moul/txlink/txlink.gno b/examples/gno.land/p/moul/txlink/txlink.gno index b88fb1ede16..0aa7e8614e2 100644 --- a/examples/gno.land/p/moul/txlink/txlink.gno +++ b/examples/gno.land/p/moul/txlink/txlink.gno @@ -134,9 +134,9 @@ func (r Realm) prefix() string { } // local realm -> /realm - realm := string(r) - if strings.HasPrefix(realm, chainDomain) { - return strings.TrimPrefix(realm, chainDomain) + rlm := string(r) + if strings.HasPrefix(rlm, chainDomain) { + return strings.TrimPrefix(rlm, chainDomain) } // remote realm -> https://remote.land/realm From 1743abfb9e79addc0fcdf16e59f1005e05fcdf65 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:30:27 +0300 Subject: [PATCH 45/83] fix r/demo/atomicswap --- examples/gno.land/r/demo/atomicswap/atomicswap_test.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/demo/atomicswap/atomicswap_test.gno b/examples/gno.land/r/demo/atomicswap/atomicswap_test.gno index eaf26a56b2b..635c70e065d 100644 --- a/examples/gno.land/r/demo/atomicswap/atomicswap_test.gno +++ b/examples/gno.land/r/demo/atomicswap/atomicswap_test.gno @@ -341,7 +341,6 @@ func TestNewGRC20Swap_Refund(t *testing.T) { rlm := std.DerivePkgAddr("gno.land/r/demo/atomicswap") hashlock := sha256.Sum256([]byte("secret")) hashlockHex := hex.EncodeToString(hashlock[:]) - timelock := time.Now().Add(defaultTimelockDuration) test20.PrivateLedger.Mint(sender, 100_000) test20.PrivateLedger.Approve(sender, rlm, 70_000) From 5a953fa0a1b46edb08fec4ec15f1bbdfaca44b2d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:35:35 +0300 Subject: [PATCH 46/83] fix p/moul/helplink --- examples/gno.land/p/moul/helplink/helplink.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/p/moul/helplink/helplink.gno b/examples/gno.land/p/moul/helplink/helplink.gno index d1a03759cdf..cd8028c30d5 100644 --- a/examples/gno.land/p/moul/helplink/helplink.gno +++ b/examples/gno.land/p/moul/helplink/helplink.gno @@ -51,9 +51,9 @@ func (r Realm) prefix() string { } // local realm -> /realm - realm := string(r) - if strings.HasPrefix(realm, chainDomain) { - return strings.TrimPrefix(realm, chainDomain) + rlm := string(r) + if strings.HasPrefix(rlm, chainDomain) { + return strings.TrimPrefix(rlm, chainDomain) } // remote realm -> https://remote.land/realm From e8c6bbc8df3d41cf5c7c69323d96904a367effb0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:36:52 +0300 Subject: [PATCH 47/83] fix r/gnoland/monit --- examples/gno.land/r/gnoland/monit/monit_test.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/gnoland/monit/monit_test.gno b/examples/gno.land/r/gnoland/monit/monit_test.gno index b08f30cb632..362a05c6fad 100644 --- a/examples/gno.land/r/gnoland/monit/monit_test.gno +++ b/examples/gno.land/r/gnoland/monit/monit_test.gno @@ -78,7 +78,6 @@ func TestReset(t *testing.T) { // Initial state check initialCounter := counter initialLastUpdate := lastUpdate - initialLastCaller := lastCaller initialStatus := wd.Status() // Call Incr to change the state From b653d6c012c9a220fb5db20434355205509c2221 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 20:37:52 +0200 Subject: [PATCH 48/83] fix r/gov/dao/v3/memberstore --- examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno index e8f68f835c2..bb5f5aed8d6 100644 --- a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno +++ b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno @@ -122,9 +122,9 @@ func Render(string) string { // Get gets the Members store func Get() MembersByTier { - realm := std.CurrentRealm().PkgPath() - if !dao.InAllowedDAOs(realm) { - panic("this Realm is not allowed to get the Members data: " + realm) + currealm := std.CurrentRealm().PkgPath() + if !dao.InAllowedDAOs(currealm) { + panic("this Realm is not allowed to get the Members data: " + currealm) } return members From a7d74e79cce0eb036fc9d6f10765c0de6b843f1b Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 20:38:09 +0200 Subject: [PATCH 49/83] fix: generate missing gno.mod files Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod | 3 +++ examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod | 3 +++ examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod | 3 +++ .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod | 3 +++ .../r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod | 3 +++ .../r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod | 3 +++ .../r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod | 3 +++ 13 files changed, 39 insertions(+) create mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod create mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod create mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod new file mode 100644 index 00000000000..f4b54dfa505 --- /dev/null +++ b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx + +gno 0.9 From 9d643a8bb0ce1b1f0191eaaf93008c3d3feaed1e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 20:40:26 +0200 Subject: [PATCH 50/83] fix: p/moul/helplink Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/moul/helplink/helplink.gno | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/p/moul/helplink/helplink.gno b/examples/gno.land/p/moul/helplink/helplink.gno index d1a03759cdf..55bcf4c24a0 100644 --- a/examples/gno.land/p/moul/helplink/helplink.gno +++ b/examples/gno.land/p/moul/helplink/helplink.gno @@ -51,13 +51,13 @@ func (r Realm) prefix() string { } // local realm -> /realm - realm := string(r) - if strings.HasPrefix(realm, chainDomain) { - return strings.TrimPrefix(realm, chainDomain) + rlmstr := string(r) + if strings.HasPrefix(rlmstr, chainDomain) { + return strings.TrimPrefix(rlmstr, chainDomain) } // remote realm -> https://remote.land/realm - return "https://" + string(r) + return "https://" + rlmstr } // Func returns a markdown link for the specified function with optional From 6aac30c641ea667661d0cfc90c91f61f4ffba64f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:43:57 +0300 Subject: [PATCH 51/83] a few more simple typecheck fix --- examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno | 6 +++--- examples/gno.land/r/morgan/chess/chess_test.gno | 2 +- examples/gno.land/r/morgan/chess/lobby_test.gno | 2 +- examples/gno.land/r/sys/params/unlock_test.gno | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno index e8f68f835c2..21cfe84ed3d 100644 --- a/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno +++ b/examples/gno.land/r/gov/dao/v3/memberstore/memberstore.gno @@ -122,9 +122,9 @@ func Render(string) string { // Get gets the Members store func Get() MembersByTier { - realm := std.CurrentRealm().PkgPath() - if !dao.InAllowedDAOs(realm) { - panic("this Realm is not allowed to get the Members data: " + realm) + rlm := std.CurrentRealm().PkgPath() + if !dao.InAllowedDAOs(rlm) { + panic("this Realm is not allowed to get the Members data: " + rlm) } return members diff --git a/examples/gno.land/r/morgan/chess/chess_test.gno b/examples/gno.land/r/morgan/chess/chess_test.gno index a6b7669ce48..d5547366d2e 100644 --- a/examples/gno.land/r/morgan/chess/chess_test.gno +++ b/examples/gno.land/r/morgan/chess/chess_test.gno @@ -587,7 +587,7 @@ func runCommandTest(t *testing.T, command string) { t.Run(testName, func(t *testing.T) { cleanup() bufs := make(map[string]string, 3) - for idx, f := range funcs { + for _, f := range funcs { if _, ok := f.(interface{ Checker() }); ok { f.Run(t, bufs) } else { diff --git a/examples/gno.land/r/morgan/chess/lobby_test.gno b/examples/gno.land/r/morgan/chess/lobby_test.gno index 4efadcab02d..b336188e585 100644 --- a/examples/gno.land/r/morgan/chess/lobby_test.gno +++ b/examples/gno.land/r/morgan/chess/lobby_test.gno @@ -153,7 +153,7 @@ func TestLobbyGameFound(t *testing.T) { } testing.SetRealm(std.NewUserRealm(tc.caller)) - game := cross(LobbyGameFound)() + cross(LobbyGameFound)() if tc.check != nil { tc.check(t) diff --git a/examples/gno.land/r/sys/params/unlock_test.gno b/examples/gno.land/r/sys/params/unlock_test.gno index b6ef7813eb3..c8544256bbb 100644 --- a/examples/gno.land/r/sys/params/unlock_test.gno +++ b/examples/gno.land/r/sys/params/unlock_test.gno @@ -7,7 +7,7 @@ import ( "gno.land/p/demo/testutils" "gno.land/p/demo/urequire" "gno.land/r/gov/dao" - "gno.land/r/gov/dao/v3/init" + ini "gno.land/r/gov/dao/v3/init" ) var ( @@ -16,7 +16,7 @@ var ( func init() { testing.SetRealm(std.NewUserRealm(g1user)) - init.InitWithUsers(g1user) + ini.InitWithUsers(g1user) } func TestProUnlockTransfer(t *testing.T) { @@ -48,7 +48,7 @@ func TestExeUnlockTransfer(t *testing.T) { pr := ProposeUnlockTransferRequest() id := cross(dao.MustCreateProposal)(pr) - p, err := cross(dao.GetProposal)(id) + _, err := cross(dao.GetProposal)(id) urequire.NoError(t, err) // urequire.True(t, dao.Active == p.Status()) // TODO From edb8830ccc620257376bf5e70c6441190273fe91 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 20:45:30 +0200 Subject: [PATCH 52/83] Revert "fix: generate missing gno.mod files" This reverts commit a7d74e79cce0eb036fc9d6f10765c0de6b843f1b. --- examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod | 3 --- examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod | 3 --- examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod | 3 --- 13 files changed, 39 deletions(-) delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 From 54a2a35222d507e241dc65b42d58a44c27ad3707 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 20 May 2025 21:47:49 +0300 Subject: [PATCH 53/83] fix r/x/nir1218_evaluation_ --- .../gno.land/r/x/nir1218_evaluation_proposal/committee_test.gno | 2 +- .../r/x/nir1218_evaluation_proposal/evaluation_test.gno | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gno.land/r/x/nir1218_evaluation_proposal/committee_test.gno b/examples/gno.land/r/x/nir1218_evaluation_proposal/committee_test.gno index 4dd72c5d616..68e8cbe8c19 100644 --- a/examples/gno.land/r/x/nir1218_evaluation_proposal/committee_test.gno +++ b/examples/gno.land/r/x/nir1218_evaluation_proposal/committee_test.gno @@ -65,7 +65,7 @@ func TestCategoryEvaluationCriteria(t *testing.T) { testing.SetOriginCaller(member) approved := c.ApproveCategory(category, VoteYes) if !approved { - value, exists := c.categories.Get(category) + value, _ := c.categories.Get(category) gotCategory := value.(*Category) t.Errorf("Approved First Committee category got %s expected %s", gotCategory.status, "Approved") } diff --git a/examples/gno.land/r/x/nir1218_evaluation_proposal/evaluation_test.gno b/examples/gno.land/r/x/nir1218_evaluation_proposal/evaluation_test.gno index f9e0913010d..176023dc806 100644 --- a/examples/gno.land/r/x/nir1218_evaluation_proposal/evaluation_test.gno +++ b/examples/gno.land/r/x/nir1218_evaluation_proposal/evaluation_test.gno @@ -28,7 +28,7 @@ var ( func TestEvaluationAddContribution(t *testing.T) { pr := NewPullRequest(id, name, description, status, category) - contributionId, ok := e.AddContribution(pr, address) + contributionId, _ := e.AddContribution(pr, address) t.Run("", func(t *testing.T) { if contributionId != id { From 427ac064789beb56c35df6284d4ad52045b74c2f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 20:45:30 +0200 Subject: [PATCH 54/83] Revert "fix: generate missing gno.mod files" This reverts commit a7d74e79cce0eb036fc9d6f10765c0de6b843f1b. --- examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod | 3 --- examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod | 3 --- examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod | 3 --- .../gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod | 3 --- .../r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod | 3 --- 13 files changed, 39 deletions(-) delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod delete mode 100644 examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod delete mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod b/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/jeronimo_render_proxy/home/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_a/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_b/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/home/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v1impl/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 diff --git a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod b/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod deleted file mode 100644 index f4b54dfa505..00000000000 --- a/examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_f/v2impl/gno.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx - -gno 0.9 From 241cbbefec15d5d43961ff82e14105abdb9197a7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Tue, 20 May 2025 21:51:52 +0200 Subject: [PATCH 55/83] fix printf usage in gno fix --- gnovm/cmd/gno/tool_fix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index afce2eb6d58..fffce3fbaf1 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -147,7 +147,7 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { // FIX STAGE 1: Type-check and lint. for _, dir := range dirs { if cmd.verbose { - io.ErrPrintln("fixing %q", dir) + io.ErrPrintfln("fixing %q", dir) } // Only supports directories. From c7bf362537ff980baa3ce38d040acaea0649d194 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 20 May 2025 13:56:07 -0700 Subject: [PATCH 56/83] Make filetests go .Check with completely separate go fileset --- gnovm/cmd/gno/common.go | 1 + gnovm/pkg/gnolang/gotypecheck.go | 24 +++++++++++++++++++---- gnovm/tests/files/govdao/realm_govdao.gno | 20 +++++++++++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index fb8339b843f..0242b9a8852 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -168,6 +168,7 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { } func catchPanic(dir, pkgPath string, stderr io.WriteCloser, action func()) (didPanic bool) { + // Uncomment for debugging. defer func() { // Errors catched here mostly come from: // gnovm/pkg/gnolang/preprocess.go diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 427a985fe97..c5a03c994bc 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -7,6 +7,7 @@ import ( "go/token" "go/types" "path" + "path/filepath" "slices" "strings" @@ -231,12 +232,27 @@ type realm interface{} // shim */ // STEP 4: Type-check Gno0.9 AST in Go (_filetest.gno if ParseModeAll). - // Each filetest is its own package. defer func() { gmgof.Name = ast.NewIdent(mpkg.Name) }() // revert for _, tgof := range tgofs { - gmgof.Name = tgof.Name // may be anything. - tgof2 := []*ast.File{gmgof, tgof} - _, _ = gimp.cfg.Check(mpkg.Path, gofset, tgof2, nil) + // Each filetest is its own package. + // XXX If we're re-parsing the filetest anyways, + // change GoParseMemPackage to not parse into tgofs. + tfname := filepath.Base(gofset.File(tgof.Pos()).Name()) + tfile := mpkg.GetFile(tfname) + tmpkg := &std.MemPackage{Name: tgof.Name.String(), Path: mpkg.Path} + tmpkg.NewFile(tfname, tfile.Body) + tgofset, _, _, tgofs2, _ := GoParseMemPackage(tmpkg, ParseModeAll) + if len(gimp.errors) != numErrs { + /* NOTE: Uncomment to fail earlier. + errs = multierr.Combine(gimp.errors...) + return + */ + continue + } + if len(tgofs2) != 1 { // should not happen + panic("unexpected GoParseMemPackage result") + } + _, _ = gimp.cfg.Check(tmpkg.Path, tgofset, tgofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { errs = multierr.Combine(gimp.errors...) diff --git a/gnovm/tests/files/govdao/realm_govdao.gno b/gnovm/tests/files/govdao/realm_govdao.gno index ba1716db17f..ca04ef7132c 100644 --- a/gnovm/tests/files/govdao/realm_govdao.gno +++ b/gnovm/tests/files/govdao/realm_govdao.gno @@ -71,5 +71,21 @@ func Render() { println(dao.Render("")) } -// Error: -// gno.land/r/gov/dao/v3/memberstore/memberstore.gno:125:2-7: builtin identifiers cannot be shadowed: realm +// Output: +// true +// # Active Proposals: +// ## Proposal with id: 0 +// ### Title: Proposal Title: Dummy proposal +// +// ### Proposed by: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// Description: Do nothing +// +// +// ### Proposal Status: +// +// - **PROPOSAL HAS BEEN ACCEPTED** +// - Allowed tiers to vote: T1 T2 T3 +// - YES PERCENT: 66.66666666666666% +// - NO PERCENT: 0% +// - [Go to votes list](/r/gov/dao:0/votes). From 85c6d69f56384e2d371cde93daa46886e0478303 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 20 May 2025 14:27:50 -0700 Subject: [PATCH 57/83] add back .gnobuiltins.go for filetests --- gnovm/pkg/gnolang/gotypecheck.go | 38 +++++++++++++++++--------------- tm2/pkg/std/memfile.go | 7 +++--- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index c5a03c994bc..91a418e30b1 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -21,6 +21,20 @@ import ( XXX move to pkg/gnolang/importer.go. */ +func makeGnoBuiltins(pkgName string) *std.MemFile { + file := &std.MemFile{ + Name: ".gnobuiltins.go", + Body: fmt.Sprintf(`package %s + +func istypednil(x any) bool { return false } // shim +func crossing() { } // shim +func cross[F any](fn F) F { return fn } // shim +func revive[F any](fn F) any { return nil } // shim +type realm interface{} // shim +`, pkgName)} + return file +} + // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. type MemPackageGetter interface { @@ -172,20 +186,8 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo panic("unexpected xxx_test and *_filetest.gno tests") } - // STEP 3: Add .gnobuiltins.go file. - file := &std.MemFile{ - Name: ".gnobuiltins.go", - Body: fmt.Sprintf(`package %s - -func istypednil(x any) bool { return false } // shim -func crossing() { } // shim -func cross[F any](fn F) F { return fn } // shim -func revive[F any](fn F) any { return nil } // shim -type realm interface{} // shim -`, mpkg.Name), - } - - // STEP 3: Parse .gnobuiltins.go file. + // STEP 3: Add and Parse .gnobuiltins.go file. + file := makeGnoBuiltins(mpkg.Name) const parseOpts = parser.ParseComments | parser.DeclarationErrors | parser.SkipObjectResolution @@ -238,9 +240,12 @@ type realm interface{} // shim // XXX If we're re-parsing the filetest anyways, // change GoParseMemPackage to not parse into tgofs. tfname := filepath.Base(gofset.File(tgof.Pos()).Name()) + tpname := tgof.Name.String() tfile := mpkg.GetFile(tfname) - tmpkg := &std.MemPackage{Name: tgof.Name.String(), Path: mpkg.Path} + tmpkg := &std.MemPackage{Name: tpname, Path: mpkg.Path} tmpkg.NewFile(tfname, tfile.Body) + bfile := makeGnoBuiltins(tpname) + tmpkg.AddFile(bfile) tgofset, _, _, tgofs2, _ := GoParseMemPackage(tmpkg, ParseModeAll) if len(gimp.errors) != numErrs { /* NOTE: Uncomment to fail earlier. @@ -249,9 +254,6 @@ type realm interface{} // shim */ continue } - if len(tgofs2) != 1 { // should not happen - panic("unexpected GoParseMemPackage result") - } _, _ = gimp.cfg.Check(tmpkg.Path, tgofset, tgofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 427144afb7e..6ad3a105442 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -160,17 +160,18 @@ func (mpkg *MemPackage) GetFile(name string) *MemFile { return nil } -func (mpkg *MemPackage) appendFile(mfile *MemFile) { +// Adds a file to the package without validation. +func (mpkg *MemPackage) AddFile(mfile *MemFile) { mpkg.Files = append(mpkg.Files, mfile) } -// Creates a new MemFile and appends without validation. +// Creates a new MemFile and adds without validation. func (mpkg *MemPackage) NewFile(name string, body string) (mfile *MemFile) { mfile = &MemFile{ Name: name, Body: body, } - mpkg.appendFile(mfile) + mpkg.AddFile(mfile) return } From 0c1be82bca7e19e53b5d7256c8d1b0b01d151f8a Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 20 May 2025 14:33:40 -0700 Subject: [PATCH 58/83] ... --- gnovm/pkg/gnolang/gotypecheck.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 91a418e30b1..fde091bb6fb 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -246,7 +246,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo tmpkg.NewFile(tfname, tfile.Body) bfile := makeGnoBuiltins(tpname) tmpkg.AddFile(bfile) - tgofset, _, _, tgofs2, _ := GoParseMemPackage(tmpkg, ParseModeAll) + tgofset, tgofs2, _, _, _ := GoParseMemPackage(tmpkg, ParseModeAll) if len(gimp.errors) != numErrs { /* NOTE: Uncomment to fail earlier. errs = multierr.Combine(gimp.errors...) From 646142403d11277398e405a17d4081d4087378a5 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 20 May 2025 14:46:37 -0700 Subject: [PATCH 59/83] ... --- gnovm/pkg/gnolang/gotypecheck.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index fde091bb6fb..09c9c06f0e0 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -23,7 +23,7 @@ import ( func makeGnoBuiltins(pkgName string) *std.MemFile { file := &std.MemFile{ - Name: ".gnobuiltins.go", + Name: ".gnobuiltins.gno", // because GoParseMemPackage expects .gno. Body: fmt.Sprintf(`package %s func istypednil(x any) bool { return false } // shim @@ -197,7 +197,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo file.Body, parseOpts) if err != nil { - panic("error parsing gotypecheck gnobuiltins.go file") + panic("error parsing gotypecheck .gnobuiltins.gno file") } // NOTE: When returning errs from this function, @@ -246,7 +246,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo tmpkg.NewFile(tfname, tfile.Body) bfile := makeGnoBuiltins(tpname) tmpkg.AddFile(bfile) - tgofset, tgofs2, _, _, _ := GoParseMemPackage(tmpkg, ParseModeAll) + tgofset, tgofs, _, ttgofs, _ := GoParseMemPackage(tmpkg, ParseModeAll) if len(gimp.errors) != numErrs { /* NOTE: Uncomment to fail earlier. errs = multierr.Combine(gimp.errors...) @@ -254,7 +254,9 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo */ continue } - _, _ = gimp.cfg.Check(tmpkg.Path, tgofset, tgofs2, nil) + ttgofs2 := append(ttgofs, tgofs...) + + _, _ = gimp.cfg.Check(tmpkg.Path, tgofset, ttgofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { errs = multierr.Combine(gimp.errors...) From 8d0bf15c0900e1e11d88168c9d44d35f1de4ae3c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Tue, 20 May 2025 15:25:33 -0700 Subject: [PATCH 60/83] future-proof ATTR_PREPROCESS_SKIPPED --- gnovm/pkg/gnolang/preprocess.go | 48 ++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 11700ae6448..712e72eb931 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2943,9 +2943,9 @@ func addHeapCapture(dbn BlockNode, fle *FuncLitExpr, depth int, nx *NameExpr) (i panic("should not happen, idx not found") } -// finds the first FuncLitExpr in the stack at or after stop. -// returns the depth of first closure, 1 if stop itself is a closure, -// or 0 if not found. +// finds the first FuncLitExpr in the stack after (excluding) stop. returns +// the depth of first closure, 1 if last stack item itself is a closure, or 0 +// if not found. func findFirstClosure(stack []BlockNode, stop BlockNode) (fle *FuncLitExpr, depth int, found bool) { faux := 0 // count faux block for i := len(stack) - 1; i >= 0; i-- { @@ -2975,6 +2975,35 @@ func findFirstClosure(stack []BlockNode, stop BlockNode) (fle *FuncLitExpr, dept return } +// finds the last FuncLitExpr in the stack at (including) or after stop. +// returns the depth of last function, 1 if last stack item itself is a +// closure, or 0 if not found. +func findLastFunction(last BlockNode, stop BlockNode) (fn BlockNode, depth int, found bool) { + faux := 0 // count faux block + depth_ := 0 // working value + for stbn := last; stbn != stop; stbn = stbn.GetParentNode(nil) { + depth_ += 1 + switch stbn := stbn.(type) { + case *FuncLitExpr, *FuncDecl: + fn = stbn + depth = depth_ - faux + found = true + return + default: + if fauxChildBlockNode(stbn) { + faux++ + } + if stbn == stop { + return + } + } + } + // This can happen e.g. if stop is a package but we are + // Preprocess()'ing an expression such as `func(){ ... }()` from + // Machine.Eval() on an already preprocessed package. + return +} + // If a name is used as a heap item, Convert all other uses of such names // for heap use. If a name of type heap define is not actually used // as heap use, demotes them. @@ -4014,17 +4043,10 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin if un != "" { return } - // only skip when no outer funcDecl or funcLit - for last != nil { - switch last.(type) { - case *FuncDecl, *FuncLitExpr: - return - } - last = last.GetParentNode(nil) + _, _, found := findLastFunction(last, nil) + if !found { + cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") } - - cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") - case *FieldTypeExpr: // FIELD return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) case *ArrayTypeExpr: From 14d28e89c2771927b39c908132d552809f82d8ac Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 00:18:16 -0700 Subject: [PATCH 61/83] lint and fix fixes regarding preprocessed package node and store caching --- gnovm/cmd/gno/common.go | 81 +++++++++-- gnovm/cmd/gno/tool_fix.go | 185 +++++++++++++++++--------- gnovm/cmd/gno/tool_lint.go | 64 +++++---- gnovm/pkg/gnolang/gnomod.go | 3 +- gnovm/pkg/gnolang/gotypecheck.go | 15 ++- gnovm/pkg/gnolang/machine.go | 2 +- gnovm/pkg/gnolang/nodes.go | 51 ++++++- gnovm/pkg/gnolang/nodes_string.go | 2 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 27 ++-- gnovm/pkg/gnolang/version.go | 5 - gnovm/pkg/test/imports.go | 4 +- 11 files changed, 303 insertions(+), 136 deletions(-) delete mode 100644 gnovm/pkg/gnolang/version.go diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index 0242b9a8852..3c125b0c5c3 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "go/scanner" "go/types" @@ -11,6 +12,7 @@ import ( "strings" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/test" "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" ) @@ -45,14 +47,14 @@ func (i gnoIssue) String() string { // Gno parses and sorts mpkg files into the following filesets: // - fset: all normal and _test.go files in package excluding `package xxx_test` // integration *_test.gno files. -// - _tests: `package xxx_test` integration *_test.gno files, each in their -// own file set. +// - _tests: `package xxx_test` integration *_test.gno files. // - ftests: *_filetest.gno file tests, each in their own file set. func sourceAndTestFileset(mpkg *std.MemPackage) ( - all, fset *gno.FileSet, _tests, ftests []*gno.FileSet, + all, fset *gno.FileSet, _tests *gno.FileSet, ftests []*gno.FileSet, ) { all = &gno.FileSet{} fset = &gno.FileSet{} + _tests = &gno.FileSet{} for _, mfile := range mpkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // Skip non-GNO files @@ -65,14 +67,12 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( all.AddFiles(n) if string(n.PkgName) == string(mpkg.Name)+"_test" { // A xxx_file integration test is a package of its own. - fset := &gno.FileSet{} - fset.AddFiles(n) - _tests = append(_tests, fset) + _tests.AddFiles(n) } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { // A _filetest.gno is a package of its own. - fset := &gno.FileSet{} - fset.AddFiles(n) - ftests = append(ftests, fset) + ftset := &gno.FileSet{} + ftset.AddFiles(n) + ftests = append(ftests, ftset) } else { // All normal package files and, // _test.gno files that aren't xxx_test. @@ -82,6 +82,69 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( return } +func parsePkgPathDirective(body string, defaultPkgPath string) (string, error) { + dirs, err := test.ParseDirectives(bytes.NewReader([]byte(body))) + if err != nil { + return "", fmt.Errorf("error parsing directives: %w", err) + } + return dirs.FirstDefault(test.DirectivePkgPath, defaultPkgPath), nil +} + +type processedFileSet struct { + pn *gno.PackageNode + fset *gno.FileSet +} + +type processedPackage struct { + dir string // dirctory + mpkg *std.MemPackage // includes all files + normal processedFileSet // includes all prod (and some *_test.gno) files + _tests processedFileSet // includes all xxx_test *_test.gno integration files + ftests []processedFileSet // includes all *_filetest.gno filetest files +} + +func (ppkg *processedPackage) AddNormal(pn *gno.PackageNode, fset *gno.FileSet) { + if ppkg.normal != (processedFileSet{}) { + panic("normal processed fileset already set") + } + ppkg.normal = processedFileSet{pn, fset} +} + +func (ppkg *processedPackage) AddUnderscoreTests(pn *gno.PackageNode, fset *gno.FileSet) { + if ppkg._tests != (processedFileSet{}) { + panic("_test processed fileset already set") + } + ppkg._tests = processedFileSet{pn, fset} +} + +func (ppkg *processedPackage) AddFileTest(pn *gno.PackageNode, fset *gno.FileSet) { + if len(fset.Files) != 1 { + panic("filetests must have filesets of length 1") + } + fname := fset.Files[0].Name + if !strings.HasSuffix(string(fname), "_filetest.gno") { + panic(fmt.Sprintf("expected *_filetest.gno but got %q", fname)) + } + for _, ftest := range ppkg.ftests { + if ftest.fset.Files[0].Name == fname { + panic(fmt.Sprintf("fileetest with name %q already exists", fname)) + } + } + ppkg.ftests = append(ppkg.ftests, processedFileSet{pn, fset}) +} + +func (ppkg *processedPackage) GetFileTest(fname gno.Name) processedFileSet { + if !strings.HasSuffix(string(fname), "_filetest.gno") { + panic(fmt.Sprintf("expected *_filetest.gno but got %q", fname)) + } + for _, ftest := range ppkg.ftests { + if ftest.fset.Files[0].Name == fname { + return ftest + } + } + panic(fmt.Sprintf("processedFileSet for filetest %q not found", fname)) +} + // reParseRecover is a regex designed to parse error details from a string. // It extracts the file location, line number, and error message from a // formatted error string. diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index fffce3fbaf1..3d360d9c485 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -7,7 +7,6 @@ import ( "fmt" "go/ast" "go/token" - "go/types" goio "io" "io/fs" "os" @@ -85,9 +84,8 @@ Also refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). */ type fixCmd struct { - verbose bool - rootDir string - autoGnomod bool + verbose bool + rootDir string // min_confidence: minimum confidence of a problem to print it // (default 0.8) auto-fix: apply suggested fixes automatically. } @@ -113,7 +111,6 @@ func (c *fixCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar(&c.verbose, "v", false, "verbose output when fixning") fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)") - fs.BoolVar(&c.autoGnomod, "auto-gnomod", true, "auto-generate gno.mod file if not already present.") } func execFix(cmd *fixCmd, args []string, io commands.IO) error { @@ -161,18 +158,11 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { fpath := path.Join(dir, "gno.mod") mod, err := gnomod.ParseFilepath(fpath) if errors.Is(err, fs.ErrNotExist) { - if cmd.autoGnomod { - modstr := gno.GenGnoModDefault("gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx") - mod, err = gnomod.ParseBytes("gno.mod", []byte(modstr)) - if err != nil { - panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) - } - io.ErrPrintfln("auto-generated %q", fpath) - err = mod.WriteFile(fpath) - if err != nil { - panic(fmt.Errorf("unexpected panic writing to %q: %w", fpath, err)) - } - // err == nil. + // Make a temporary gno.mod (but don't write it yet) + modstr := gno.GenGnoModMissing("gno.land/r/xxx_myrealm_xxx/xxx_fixme_xxx") + mod, err = gnomod.ParseBytes("gno.mod", []byte(modstr)) + if err != nil { + panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) } } if err != nil { @@ -213,8 +203,7 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { gs := ts.BeginTransaction(cw, cw, nil) // These are Go types. - var pn *gno.PackageNode - var _ *types.Package + var ppkg = processedPackage{mpkg: mpkg, dir: dir} var gofset *token.FileSet var gofs, _gofs, tgofs []*ast.File var errs error @@ -247,51 +236,93 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { defer tm.Release() // Prepare Go AST for preprocessing. - if mod.GetGno() == "0.0" { - allgofs := append(gofs, _gofs...) - allgofs = append(allgofs, tgofs...) - errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) - if errs != nil { - io.ErrPrintln(errs) - hasError = true - return // Prepare must succeed. - } + allgofs := append(gofs, _gofs...) + allgofs = append(allgofs, tgofs...) + errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) + if errs != nil { + io.ErrPrintln(errs) + hasError = true + return // Prepare must succeed. } // FIX STEP 5: re-parse // Gno parse source fileset and test filesets. - all, fset, _tests, ftests := sourceAndTestFileset(mpkg) - - // FIX STEP 6: PreprocessFiles() - // Preprocess fset files (w/ some _test.gno). - pn, _ = tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) - // Preprocess _test files (all _test.gno). - for _, fset := range _tests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) - } - // Preprocess _filetest.gno files. - for _, fset := range ftests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) + _, fset, _tests, ftests := sourceAndTestFileset(mpkg) + + { + // FIX STEP 6: PreprocessFiles() + // Preprocess fset files (w/ some _test.gno). + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + tm.Store = gs + pn, _ := tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false, gno.GnoVerMissing) + ppkg.AddNormal(pn, fset) + + // FIX STEP 7: FindXforms(): + // FindXforms for all files if outdated. + // Use the preprocessor to collect the + // transformations needed to be done. + // They are collected in + // pn.GetAttribute("XREALMFORM") + for _, fn := range fset.Files { + gno.FindXformsGno0p9(gs, pn, fn) + } } - - // Record results. - ppkgs[dir] = processedPackage{ - mpkg, fset, pn, _tests, ftests} - - // FIX STEP 7: FindXforms(): - // FindXforms for all files if outdated. - if mod.GetGno() == "0.0" { + { + // FIX STEP 6: PreprocessFiles() + // Preprocess xxx_test files (some _test.gno). + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + tm.Store = gs + pn, _ := tm.PreprocessFiles( + mpkg.Name+"_test", mpkg.Path+"_test", _tests, false, false, gno.GnoVerMissing) + ppkg.AddUnderscoreTests(pn, _tests) + + // FIX STEP 7: FindXforms(): + // FindXforms for all files if outdated. // Use the preprocessor to collect the // transformations needed to be done. // They are collected in // pn.GetAttribute("XREALMFORM") - for _, fn := range all.Files { + for _, fn := range _tests.Files { gno.FindXformsGno0p9(gs, pn, fn) } } + { + // FIX STEP 6: PreprocessFiles() + // Preprocess _filetest.gno files. + for i, fset := range ftests { + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + tm.Store = gs + fname := string(fset.Files[0].Name) + mfile := mpkg.GetFile(fname) + pkgPath := fmt.Sprintf("%s_filetest%d", mpkg.Path, i) + pkgPath, err = parsePkgPathDirective(mfile.Body, pkgPath) + if err != nil { + io.ErrPrintln(err) + hasError = true + continue + } + pkgName := string(fset.Files[0].PkgName) + pn, _ := tm.PreprocessFiles(pkgName, pkgPath, fset, false, false, gno.GnoVerMissing) + ppkg.AddFileTest(pn, fset) + + // FIX STEP 7: FindXforms(): + // FindXforms for all files if outdated. + // Use the preprocessor to collect the + // transformations needed to be done. + // They are collected in + // pn.GetAttribute("XREALMFORM") + for _, fn := range fset.Files { + gno.FindXformsGno0p9(gs, pn, fn) + } + } + } + + // Record results. + ppkgs[dir] = ppkg }) if didPanic { hasError = true @@ -307,24 +338,39 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { for _, dir := range dirs { ppkg, ok := ppkgs[dir] if !ok { - // XXX fix this; happens when fixing a file. - // XXX see comment on top of this file. - panic("missing package; gno fix currently only supports directories.") + // Happens when fixing a file, (XXX fix this case) + // but also happens when preprocessing isn't needed. + continue } - mpkg, pn := ppkg.mpkg, ppkg.pn - // If gno version is already 0.9, skip. - mod, err := gno.ParseCheckGnoMod(mpkg) - if mod.GetGno() == "0.9" { // XXX - continue + // Sanity check. + mod, err := gno.ParseCheckGnoMod(ppkg.mpkg) + if mod.GetGno() != gno.GnoVerMissing { + panic("should not happen") } // FIX STEP 8 & 9: gno.TranspileGno0p9() Part 1 & 2 - xforms1, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XFORMS).(map[string]struct{}) - err = gno.TranspileGno0p9(mpkg, dir, xforms1) + mpkg := ppkg.mpkg + transpileProcessedFileSet := func(pfs processedFileSet) error { + pn, fset := pfs.pn, pfs.fset + xforms1, _ := pn.GetAttribute(gno.ATTR_GNO0P9_XFORMS).(map[string]struct{}) + err = gno.TranspileGno0p9(mpkg, dir, pn, fset.GetFileNames(), xforms1) + return err + } + err = transpileProcessedFileSet(ppkg.normal) + if err != nil { + return err + } + err = transpileProcessedFileSet(ppkg._tests) if err != nil { return err } + for _, ftest := range ppkg.ftests { + err = transpileProcessedFileSet(ftest) + if err != nil { + return err + } + } } if hasError { return commands.ExitCodeError(1) @@ -336,11 +382,22 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { for _, dir := range dirs { ppkg, ok := ppkgs[dir] if !ok { - panic("where did it go") + // Happens when fixing a file, (XXX fix this case) + // but also happens when preprocessing isn't needed. + continue + } + + // Write version to gno.mod. + mod, err := gno.ParseCheckGnoMod(ppkg.mpkg) + if err != nil { + // should have been auto-generated. + panic("missing gno.mod") } + mod.SetGno(gno.GnoVerLatest) + ppkg.mpkg.SetFile("gno.mod", mod.WriteString()) // FIX STEP 10: mpkg.WriteTo(): - err := ppkg.mpkg.WriteTo(dir) + err = ppkg.mpkg.WriteTo(dir) if err != nil { return err } diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 8ca0882e161..93a73b208a6 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -28,14 +28,6 @@ import ( Refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). */ -type processedPackage struct { - mpkg *std.MemPackage - fset *gno.FileSet - pn *gno.PackageNode - _tests []*gno.FileSet - ftests []*gno.FileSet -} - type lintCmd struct { verbose bool rootDir string @@ -170,7 +162,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { gs := ts.BeginTransaction(cw, cw, nil) // These are Go types. - var pn *gno.PackageNode + var ppkg = processedPackage{mpkg: mpkg, dir: dir} var errs error // Run type checking @@ -202,27 +194,47 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // Gno parse source fileset and test filesets. _, fset, _tests, ftests := sourceAndTestFileset(mpkg) - // LINT STEP 5: PreprocessFiles() - // Preprocess fset files (w/ some _test.gno). - pn, _ = tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) - // LINT STEP 5: PreprocessFiles() - // Preprocess _test files (all _test.gno). - for _, fset := range _tests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) + { + // LINT STEP 5: PreprocessFiles() + // Preprocess fset files (w/ some _test.gno). + pn, _ := tm.PreprocessFiles( + mpkg.Name, mpkg.Path, fset, false, false, "") + ppkg.AddNormal(pn, fset) } - // LINT STEP 5: PreprocessFiles() - // Preprocess _filetest.gno files. - for _, fset := range ftests { - tm.PreprocessFiles( - mpkg.Name, mpkg.Path, fset, false, false) + { + // LINT STEP 5: PreprocessFiles() + // Preprocess _test files (all _test.gno). + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + tm.Store = gs + pn, _ := tm.PreprocessFiles( + mpkg.Name, mpkg.Path, _tests, false, false, "") + ppkg.AddUnderscoreTests(pn, _tests) + } + { + // LINT STEP 5: PreprocessFiles() + // Preprocess _filetest.gno files. + for i, fset := range ftests { + cw := bs.CacheWrap() + gs := ts.BeginTransaction(cw, cw, nil) + tm.Store = gs + fname := string(fset.Files[0].Name) + mfile := mpkg.GetFile(fname) + pkgPath := fmt.Sprintf("%s_filetest%d", mpkg.Path, i) + pkgPath, err = parsePkgPathDirective(mfile.Body, pkgPath) + if err != nil { + io.ErrPrintln(err) + hasError = true + continue + } + pkgName := string(fset.Files[0].PkgName) + pn, _ := tm.PreprocessFiles(pkgName, pkgPath, fset, false, false, "") + ppkg.AddFileTest(pn, fset) + } } // Record results. - ppkgs[dir] = processedPackage{ - mpkg, fset, pn, _tests, ftests, - } + ppkgs[dir] = ppkg }) if didPanic { hasError = true diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index c8f4d53ed25..19ea58d8e8d 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -24,6 +24,7 @@ gno {{.GnoVersion}}` func GenGnoModLatest(pkgPath string) string { return genGnoMod(pkgPath, GnoVerLatest) } func GenGnoModTesting(pkgPath string) string { return genGnoMod(pkgPath, GnoVerTesting) } func GenGnoModDefault(pkgPath string) string { return genGnoMod(pkgPath, GnoVerDefault) } +func GenGnoModMissing(pkgPath string) string { return genGnoMod(pkgPath, GnoVerMissing) } func genGnoMod(pkgPath string, gnoVersion string) string { buf := new(bytes.Buffer) @@ -66,7 +67,7 @@ func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { } else if mod.Gno == nil { // gno.mod was never specified; set missing. mod.SetGno(GnoVerMissing) - } else if mod.Gno.Version == GnoVersion { + } else if mod.Gno.Version == GnoVerLatest { // current version, nothing to do. } else { panic("unsupported gno version " + mod.Gno.Version) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 09c9c06f0e0..71af7af87e4 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -197,7 +197,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo file.Body, parseOpts) if err != nil { - panic("error parsing gotypecheck .gnobuiltins.gno file") + panic(fmt.Errorf("error parsing gotypecheck .gnobuiltins.gno file: %w", err)) } // NOTE: When returning errs from this function, @@ -225,7 +225,7 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo defer func() { gmgof.Name = ast.NewIdent(mpkg.Name) }() // revert } _gofs2 := append(_gofs, gmgof) - _, _ = gimp.cfg.Check(mpkg.Path, gofset, _gofs2, nil) + _, _ = gimp.cfg.Check(mpkg.Path+"_test", gofset, _gofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { errs = multierr.Combine(gimp.errors...) @@ -242,11 +242,14 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo tfname := filepath.Base(gofset.File(tgof.Pos()).Name()) tpname := tgof.Name.String() tfile := mpkg.GetFile(tfname) - tmpkg := &std.MemPackage{Name: tpname, Path: mpkg.Path} + // XXX If filetest are having issues, consider this: + // pkgPath := fmt.Sprintf("%s_filetest%d", mpkg.Path, i) + pkgPath := mpkg.Path + tmpkg := &std.MemPackage{Name: tpname, Path: pkgPath} tmpkg.NewFile(tfname, tfile.Body) bfile := makeGnoBuiltins(tpname) tmpkg.AddFile(bfile) - tgofset, tgofs, _, ttgofs, _ := GoParseMemPackage(tmpkg, ParseModeAll) + gofset2, gofs2, _, tgofs2, _ := GoParseMemPackage(tmpkg, ParseModeAll) if len(gimp.errors) != numErrs { /* NOTE: Uncomment to fail earlier. errs = multierr.Combine(gimp.errors...) @@ -254,9 +257,9 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo */ continue } - ttgofs2 := append(ttgofs, tgofs...) + gofs2 = append(gofs2, tgofs2...) - _, _ = gimp.cfg.Check(tmpkg.Path, tgofset, ttgofs2, nil) + _, _ = gimp.cfg.Check(tmpkg.Path, gofset2, gofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { errs = multierr.Combine(gimp.errors...) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 19e52a16454..9be1c775974 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -463,7 +463,7 @@ func (m *Machine) RunFiles(fns ...*FileNode) { // compile-time errors in the package. It is also usde to preprocess files from // the package getter for tests, e.g. from "gnovm/tests/files/extern/*", or from // "examples/*". -func (m *Machine) PreprocessFiles(pkgName, pkgPath string, fset *FileSet, save, withOverrides bool) (*PackageNode, *PackageValue) { +func (m *Machine) PreprocessFiles(pkgName, pkgPath string, fset *FileSet, save, withOverrides bool, fixFrom string) (*PackageNode, *PackageValue) { if !withOverrides { if err := checkDuplicates(fset); err != nil { panic(fmt.Errorf("running package %q: %w", pkgName, err)) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 5f7646fdd07..333e31f6aeb 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1156,6 +1156,13 @@ type FileSet struct { Files []*FileNode } +func (fset FileSet) GetFileNames() (fnames []Name) { + for _, fnode := range fset.Files { + fnames = append(fnames, fnode.Name) + } + return +} + // PackageNameFromFileBody extracts the package name from the given Gno code body. // The 'name' parameter is used for better error traces, and 'body' contains the Gno code. func PackageNameFromFileBody(name, body string) (Name, error) { @@ -1244,13 +1251,18 @@ func MustReadMemPackage(dir string, pkgPath string) *std.MemPackage { // No parsing or validation is done on the filenames. // // NOTE: errors out if package name is invalid (characters must be alphanumeric or _, -// lowercase, and must start with a letter). +// lowercase, and must start with a letter, and be the same for normal files +// and normal *_test.gno files, and xxx_test for integration tests). Filetest +// package names are not checked. If the only file present is a single filetest, +// its package name is used. // // XXX TODO pkgPath should instead be derived by inspecting the contents, among them // the gno.mod file. func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, error) { mpkg := &std.MemPackage{Path: pkgPath} - var pkgName Name + var pkgName Name // normal file pkg name + var pkgNameFT Name // filetest pkg name + var pkgNameFTDifferent bool // if pkgNameFT are different for _, fpath := range list { fname := filepath.Base(fpath) bz, err := os.ReadFile(fpath) @@ -1258,13 +1270,31 @@ func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, err return nil, err } // XXX: should check that all pkg names are the same (else package is invalid) - if pkgName == "" && strings.HasSuffix(fname, ".gno") { - pkgName, err = PackageNameFromFileBody(path.Join(pkgPath, fname), string(bz)) + if strings.HasSuffix(fname, ".gno") { + var pkgName2 Name + pkgName2, err = PackageNameFromFileBody(path.Join(pkgPath, fname), string(bz)) if err != nil { return nil, err } - if strings.HasSuffix(string(pkgName), "_test") { - pkgName = pkgName[:len(pkgName)-len("_test")] + if strings.HasSuffix(fname, "_filetest.gno") { + // Filetests may have arbitrary package names. + // pkgName2 (of this file) may be unrelated to pkgName of the mem package. + if pkgNameFT == "" && !pkgNameFTDifferent { + pkgNameFT = pkgName2 + } else if pkgNameFT != pkgName2 { + pkgNameFT = "" + pkgNameFTDifferent = true + } + } else { + // Ensure that package names are the same. + if strings.HasSuffix(string(pkgName2), "_test") { + pkgName2 = pkgName2[:len(pkgName2)-len("_test")] + } + if pkgName == "" { + pkgName = pkgName2 + } else if pkgName != pkgName2 { + return nil, fmt.Errorf("expected package name %q but got %q", pkgName, pkgName2) + } } } mpkg.Files = append(mpkg.Files, @@ -1274,6 +1304,15 @@ func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, err }) } + // If the only file present is a single filetest, its package name is used. + if pkgName == "" && !pkgNameFTDifferent { + pkgName = pkgNameFT + } + // Still no pkgName... use a sensible default. + if pkgName == "" { + pkgName = "main" + } + mpkg.Name = string(pkgName) // If no .gno files are present, package simply does not exist. diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index d577b0b1d84..86dedc11551 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -458,7 +458,7 @@ func (x FileNode) String() string { } func (x PackageNode) String() string { - return fmt.Sprintf("package(%s)", x.PkgName) + return fmt.Sprintf("package(%s %s)", x.PkgName, x.PkgPath) } func (rn RefNode) String() string { diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 292acaaf81e..94611dcd145 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -259,7 +259,7 @@ func FindXformsGno0p9(store Store, pn *PackageNode, bn BlockNode) { case nil: return n, TRANS_CONTINUE case TypeValue: - panic("wtf") + return n, TRANS_CONTINUE case *FuncValue: if cv.IsCrossing() { // Not cross-called, so add `cur` as first argument. @@ -334,15 +334,18 @@ func addXform2IfMatched( // // Args: // - dir: where to write to. +// - pn: package node of fnames +// - fnames: file names (subset of mpkg) to transpile. // - xforms1: result of FindGno0p9Xforms(). -func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct{}) error { +func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames []Name, xforms1 map[string]struct{}) error { // Return if gno.mod is current. var mod *gnomod.File var err error mod, err = ParseCheckGnoMod(mpkg) if err == nil { - if mod.Gno.Version != "0.0" { - return fmt.Errorf("cannot transpile to gno 0.9: not gno 0.0") + if mod.GetGno() != GnoVerMissing { + return fmt.Errorf("cannot transpile to gno 0.9: expected gno 0.0 but got %s", + mod.GetGno()) } } @@ -350,11 +353,11 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct gofset := token.NewFileSet() var errs error var xall int = 0 // number translated from part 1 - for _, mfile := range mpkg.Files { - // Ignore non-gno files. - if !strings.HasSuffix(mfile.Name, ".gno") { - continue + for _, fname := range fnames { + if !strings.HasSuffix(string(fname), ".gno") { + panic(fmt.Sprintf("expected a .gno file but got %q", fname)) } + mfile := mpkg.GetFile(string(fname)) // Go parse file. const parseOpts = parser.ParseComments | parser.DeclarationErrors | @@ -397,13 +400,7 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, xforms1 map[string]struct panic("some xform items were not translated") } - // Write version to mod and to memfile named "gno.mod". - mod.SetGno(GnoVersion) - mpkg.SetFile("gno.mod", mod.WriteString()) - - // Write mempackage to dir. - err = mpkg.WriteTo(dir) - return err + return nil } // Transpile Step 1: re-key xforms1 by ast.Node. diff --git a/gnovm/pkg/gnolang/version.go b/gnovm/pkg/gnolang/version.go deleted file mode 100644 index 0a3144b21a4..00000000000 --- a/gnovm/pkg/gnolang/version.go +++ /dev/null @@ -1,5 +0,0 @@ -package gnolang - -const ( - GnoVersion = "0.9" // Gno 0.9 is the current version. -) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 8e00f0eb3e4..1b7129c2db4 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -99,7 +99,7 @@ func StoreWithOptions( return m.PreprocessFiles( mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), - save, false) + save, false, "") } else { return m.RunMemPackage(mpkg, save) } @@ -212,7 +212,7 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer, prep }) if preprocessOnly { m2.Store.AddMemPackage(mpkg) - return m2.PreprocessFiles(mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), true, true) + return m2.PreprocessFiles(mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), true, true, "") } // TODO: make this work when using gno lint. return m2.RunMemPackageWithOverrides(mpkg, true) From c7763c8e3d8de27a96f8ef4b08ab1c59b90046f2 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 20 May 2025 15:22:08 +0200 Subject: [PATCH 62/83] chore: lint --- gnovm/cmd/gno/common.go | 10 +-- gnovm/cmd/gno/tool_fix.go | 3 +- gnovm/pkg/gnolang/gnomod.go | 6 +- gnovm/pkg/gnolang/go2gno.go | 12 ---- .../internal/softfloat/runtime_softfloat64.go | 1 + gnovm/pkg/gnolang/nodes_span.go | 64 +++++++++---------- gnovm/pkg/gnolang/string_methods.go | 5 ++ gnovm/pkg/test/imports.go | 3 +- gnovm/stdlibs/std/emit_event_test.go | 4 +- 9 files changed, 51 insertions(+), 57 deletions(-) diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index 3c125b0c5c3..2fe46c26c76 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -65,7 +65,7 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( continue // Skip empty files } all.AddFiles(n) - if string(n.PkgName) == string(mpkg.Name)+"_test" { + if string(n.PkgName) == mpkg.Name+"_test" { // A xxx_file integration test is a package of its own. _tests.AddFiles(n) } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { @@ -150,9 +150,11 @@ func (ppkg *processedPackage) GetFileTest(fname gno.Name) processedFileSet { // formatted error string. // XXX: Ideally, error handling should encapsulate location details within a // dedicated error type. -const rePos = `(?:` + `\d+(?::\d+)?` + `)` // NOTE: allows the omission of columns, more relaxed than gno.Pos. -const reSpan = `(?:` + rePos + `-` + rePos + `)` -const rePosOrSpan = `(?:` + reSpan + `|` + rePos + `)` +const ( + rePos = `(?:` + `\d+(?::\d+)?` + `)` // NOTE: allows the omission of columns, more relaxed than gno.Pos. + reSpan = `(?:` + rePos + `-` + rePos + `)` + rePosOrSpan = `(?:` + reSpan + `|` + rePos + `)` +) var reParseRecover = regexp.MustCompile(`^([^:]+):(` + rePosOrSpan + `):? *(.*)$`) diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index 3d360d9c485..0d6067f6dc1 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -219,8 +219,7 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { // GoParseMemPackage(mpkg); // g.cmd.Check(); if !mod.Draft { - _, gofset, gofs, _gofs, tgofs, errs = - lintTypeCheck(io, dir, mpkg, gs) + _, gofset, gofs, _gofs, tgofs, errs = lintTypeCheck(io, dir, mpkg, gs) if errs != nil { // io.ErrPrintln(errs) already printed. hasError = true diff --git a/gnovm/pkg/gnolang/gnomod.go b/gnovm/pkg/gnolang/gnomod.go index 19ea58d8e8d..4d9c5a33e0c 100644 --- a/gnovm/pkg/gnolang/gnomod.go +++ b/gnovm/pkg/gnolang/gnomod.go @@ -13,8 +13,8 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -const gnomodTemplate = `{{/* -This is a comment in a Go template in pkg/gnolang/gnomod.go. +const gnomodTemplate = `{{/* +This is a comment in a Go template in pkg/gnolang/gnomod.go. The gnomodTemplate is used with the 'text/template' package to generate the final gno.mod file. */}} module {{.PkgPath}} @@ -63,7 +63,7 @@ func ParseCheckGnoMod(mpkg *std.MemPackage) (mod *gnomod.File, err error) { return nil, nil } else if mod, err = gnomod.ParseMemPackage(mpkg); err != nil { // error parsing gno.mod. - err = fmt.Errorf("%s/gno.mod: parse error %q", mpkg.Path, err) + err = fmt.Errorf("%s/gno.mod: parse error %w", mpkg.Path, err) } else if mod.Gno == nil { // gno.mod was never specified; set missing. mod.SetGno(GnoVerMissing) diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index 38d0e451a31..b2ad6079262 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -31,10 +31,8 @@ package gnolang */ import ( - "bytes" "fmt" "go/ast" - gofmt "go/format" "go/parser" "go/token" "os" @@ -145,16 +143,6 @@ func setSpan(fs *token.FileSet, gon ast.Node, n Node) Node { return n } -func sprintASTNode(fs *token.FileSet, gon ast.Node) string { - // Write ast.Node as string. - var buf bytes.Buffer - err := gofmt.Node(&buf, fs, gon) - if err != nil { - panic(fmt.Errorf("stringifying ast.Node: %v", err)) - } - return buf.String() -} - // If gon is a *ast.File, the name must be filled later. func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { if gon == nil { diff --git a/gnovm/pkg/gnolang/internal/softfloat/runtime_softfloat64.go b/gnovm/pkg/gnolang/internal/softfloat/runtime_softfloat64.go index 7623b9c2077..5c8898b1d59 100644 --- a/gnovm/pkg/gnolang/internal/softfloat/runtime_softfloat64.go +++ b/gnovm/pkg/gnolang/internal/softfloat/runtime_softfloat64.go @@ -418,6 +418,7 @@ func fintto64(val int64) (f uint64) { } return fpack64(fs, mant, int(mantbits64), 0) } + func fintto32(val int64) (f uint32) { fs := uint64(val) & (1 << 63) mant := uint64(val) diff --git a/gnovm/pkg/gnolang/nodes_span.go b/gnovm/pkg/gnolang/nodes_span.go index 97d5f6af5a6..747c94265ae 100644 --- a/gnovm/pkg/gnolang/nodes_span.go +++ b/gnovm/pkg/gnolang/nodes_span.go @@ -53,23 +53,23 @@ func (p Pos) GetColumn() int { return p.Column } -func (p1 Pos) Compare(p2 Pos) int { +func (p Pos) Compare(p2 Pos) int { switch { - case p1.Line < p2.Line: + case p.Line < p2.Line: return -1 - case p1.Line == p2.Line: + case p.Line == p2.Line: break - case p1.Line > p2.Line: + case p.Line > p2.Line: return 1 default: panic("should not happen") } switch { - case p1.Column < p2.Column: + case p.Column < p2.Column: return -1 - case p1.Column == p2.Column: + case p.Column == p2.Column: return 0 - case p1.Column > p2.Column: + case p.Column > p2.Column: return 1 default: panic("should not happen") @@ -116,16 +116,16 @@ func (s Span) GetSpan() Span { // Anyone with a node can still mutate these fields directly; the method guides. // If you need to override the span (e.g. constructing a Location by mutating // a copy) then call SetSpanOverride() instead of directly assigning to .Span. -func (s1 *Span) SetSpan(s2 Span) { - if !s1.IsZero() && (*s1 != s2) { - panic(".Span can ony be set once. s1:" + s1.String() + " s2:" + s2.String()) +func (s *Span) SetSpan(s2 Span) { + if !s.IsZero() && (*s != s2) { + panic(".Span can ony be set once. s:" + s.String() + " s2:" + s2.String()) } - *s1 = s2 + *s = s2 } // See documentation for SetSpan(). -func (s1 *Span) SetSpanOverride(s2 Span) { - *s1 = s2 +func (s *Span) SetSpanOverride(s2 Span) { + *s = s2 } // Overridden by Attributes.String(). @@ -153,21 +153,21 @@ func (s Span) IsZero() bool { // Start (.Pos) determines node order before .End/ .Num, // then the end (greater means containing, thus sooner), // then the num (smaller means containing, thus sooner). -func (s1 Span) Compare(s2 Span) int { - switch s1.Pos.Compare(s2.Pos) { - case -1: // s1.Pos < s2.Pos +func (s Span) Compare(s2 Span) int { + switch s.Pos.Compare(s2.Pos) { + case -1: // s.Pos < s2.Pos return -1 - case 0: // s1.Pos == s2.Pos + case 0: // s.Pos == s2.Pos break - case 1: // s1.Pos > s2.Pos + case 1: // s.Pos > s2.Pos return 1 default: panic("should not happen") } - switch s1.End.Compare(s2.End) { - case -1: // s1.End < s2.End + switch s.End.Compare(s2.End) { + case -1: // s.End < s2.End return 1 // see comment - case 0: // s1.End == s2.End + case 0: // s.End == s2.End break case 1: return -1 // see comment @@ -175,11 +175,11 @@ func (s1 Span) Compare(s2 Span) int { panic("should not happen") } switch { - case s1.Num < s2.Num: + case s.Num < s2.Num: return -1 - case s1.Num == s2.Num: + case s.Num == s2.Num: return 0 - case s1.Num > s2.Num: + case s.Num > s2.Num: return 1 default: panic("should not happen") @@ -191,20 +191,20 @@ func (s1 Span) Compare(s2 Span) int { // 2D container boxes. 2D has cardinality of 2, and span has cardinality of 1. // See Span.Compare() to see a quirk where a greater end can mean lesser span. // (we assume our 3D world has a cardinality of 3 but what if it is really 2?) -func (s1 Span) Union(s2 Span) (res Span) { - if s1.Pos.Compare(s2.Pos) < 0 { - res.Pos = s1.Pos +func (s Span) Union(s2 Span) (res Span) { + if s.Pos.Compare(s2.Pos) < 0 { + res.Pos = s.Pos } else { res.Pos = s2.Pos } - if s1.End.Compare(s2.End) < 0 { + if s.End.Compare(s2.End) < 0 { res.End = s2.End } else { - res.End = s1.End + res.End = s.End } - // Only when s1 == s2 does .Num get set. - if s1.Pos == s2.Pos && s1.End == s2.End { - res.Num = min(s1.Num, s2.Num) - 1 // maybe < 0. + // Only when s == s2 does .Num get set. + if s.Pos == s2.Pos && s.End == s2.End { + res.Num = min(s.Num, s2.Num) - 1 // maybe < 0. } else { res.Num = 0 // starts with zero. } diff --git a/gnovm/pkg/gnolang/string_methods.go b/gnovm/pkg/gnolang/string_methods.go index cc26831b481..5a2f0947773 100644 --- a/gnovm/pkg/gnolang/string_methods.go +++ b/gnovm/pkg/gnolang/string_methods.go @@ -51,6 +51,7 @@ func (i Kind) String() string { } return _Kind_name[_Kind_index[i]:_Kind_index[i+1]] } + func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. @@ -274,6 +275,7 @@ func (i Op) String() string { } return "Op(" + strconv.FormatInt(int64(i), 10) + ")" } + func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. @@ -293,6 +295,7 @@ func (i TransCtrl) String() string { } return _TransCtrl_name[_TransCtrl_index[i]:_TransCtrl_index[i+1]] } + func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. @@ -388,6 +391,7 @@ func (i TransField) String() string { } return _TransField_name[_TransField_index[i]:_TransField_index[i+1]] } + func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. @@ -426,6 +430,7 @@ func (i VPType) String() string { return "VPType(" + strconv.FormatInt(int64(i), 10) + ")" } } + func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 1b7129c2db4..4a32f09566c 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -80,9 +80,8 @@ func StoreWithOptions( // In order to translate into a newer Gno version with // the preprocessor make a slight modifications to the // AST. This needs to happen even for imports, because - // the preprocessor requries imports also preprocessed. + // the preprocessor requires imports also preprocessed. // This is because the linter uses pkg/test/imports.go. - const wtests = false // Tests don't matter for imports. gofset, gofs, _gofs, tgofs, errs := gno.GoParseMemPackage( mpkg, gno.ParseModeAll) if errs != nil { diff --git a/gnovm/stdlibs/std/emit_event_test.go b/gnovm/stdlibs/std/emit_event_test.go index 7b4c8ae9d0e..873b0ac7a0a 100644 --- a/gnovm/stdlibs/std/emit_event_test.go +++ b/gnovm/stdlibs/std/emit_event_test.go @@ -22,8 +22,8 @@ func pushFuncFrame(m *gno.Machine, name gno.Name) { PkgPath: pkgPath, File: fileName, Span: gno.Span{ // fake unique span. - Pos: gno.Pos{line, 0}, - End: gno.Pos{line, 100}, + Pos: gno.Pos{Line: line, Column: 0}, + End: gno.Pos{Line: line, Column: 100}, }, }) line++ From fef05538d99481c67b78cb76772e9c2de50e49a3 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 20 May 2025 15:47:59 +0200 Subject: [PATCH 63/83] fix: gnoland --- gno.land/pkg/gnoland/genesis.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index 6c5cc689d85..3d665a516c9 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -175,7 +175,7 @@ func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]Tx // It creates and returns a list of transactions based on these packages. func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee) ([]TxWithMetadata, error) { // list all packages from target path - pkgs, err := gnomod.ListPkgs(dir) + pkgs, err := gno.ReadPkgListFromDir(dir) if err != nil { return nil, fmt.Errorf("listing gno packages from gnomod: %w", err) } diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 7773702b7c7..96380dd2754 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -357,8 +357,8 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { } // Validate Gno syntax and type check. - format := true - if err := gno.TypeCheckMemPackage(memPkg, gnostore, format); err != nil { + _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore) + if err != nil { return ErrTypeCheck(err) } @@ -587,8 +587,8 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { } // Validate Gno syntax and type check. - format := false - if err = gno.TypeCheckMemPackage(memPkg, gnostore, format); err != nil { + _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore) + if err != nil { return "", ErrTypeCheck(err) } From 2b8794eba832ee2c3a3a9c44b43d6ebdd9c96a23 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Tue, 20 May 2025 17:50:36 +0200 Subject: [PATCH 64/83] fix: gnodev --- contribs/gnodev/cmd/gnodev/setup_loader.go | 9 +++-- contribs/gnodev/pkg/packages/package.go | 38 +++++++--------------- contribs/gnodev/pkg/packages/resolver.go | 4 --- gno.land/pkg/integration/pkgloader.go | 12 +++---- gnovm/pkg/gnomod/parse.go | 7 ++-- 5 files changed, 27 insertions(+), 43 deletions(-) diff --git a/contribs/gnodev/cmd/gnodev/setup_loader.go b/contribs/gnodev/cmd/gnodev/setup_loader.go index 69342657352..e23f4f94b6f 100644 --- a/contribs/gnodev/cmd/gnodev/setup_loader.go +++ b/contribs/gnodev/cmd/gnodev/setup_loader.go @@ -88,12 +88,11 @@ func setupPackagesResolver(logger *slog.Logger, cfg *AppConfig, dirs ...string) } func guessPathGnoMod(dir string) (path string, ok bool) { - modfile, err := gnomod.ParseAt(dir) - if err == nil { - return modfile.Module.Mod.Path, true + modfile, err := gnomod.ParseDir(dir) + if err != nil { + return "", false } - - return "", false + return modfile.Module.Mod.Path, true } var reInvalidChar = regexp.MustCompile(`[^\w_-]`) diff --git a/contribs/gnodev/pkg/packages/package.go b/contribs/gnodev/pkg/packages/package.go index f3215480ed9..bc005534128 100644 --- a/contribs/gnodev/pkg/packages/package.go +++ b/contribs/gnodev/pkg/packages/package.go @@ -1,11 +1,11 @@ package packages import ( + "errors" "fmt" "go/parser" "go/token" "os" - "path/filepath" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" @@ -27,19 +27,19 @@ type Package struct { } func ReadPackageFromDir(fset *token.FileSet, path, dir string) (*Package, error) { - modpath := filepath.Join(dir, "gno.mod") - if _, err := os.Stat(modpath); err == nil { - draft, err := isDraftFile(modpath) - if err != nil { - return nil, err - } - - // Skip draft package - // XXX: We could potentially do that in a middleware, but doing this - // here avoid to potentially parse broken files - if draft { + mod, err := gnomod.ParseDir(dir) + switch { + case err == nil: + if mod.Draft { + // Skip draft package + // XXX: We could potentially do that in a middleware, but doing this + // here avoid to potentially parse broken files return nil, ErrResolverPackageSkip } + case errors.As(err, &os.ErrNotExist): + // gno.mod is not present, continue anyway + default: + return nil, err } mempkg, err := gnolang.ReadMemPackage(dir, path) @@ -86,17 +86,3 @@ func validateMemPackage(fset *token.FileSet, mempkg *std.MemPackage) error { return nil } - -func isDraftFile(modpath string) (bool, error) { - modfile, err := os.ReadFile(modpath) - if err != nil { - return false, fmt.Errorf("unable to read file %q: %w", modpath, err) - } - - mod, err := gnomod.Parse(modpath, modfile) - if err != nil { - return false, fmt.Errorf("unable to parse `gno.mod`: %w", err) - } - - return mod.Draft, nil -} diff --git a/contribs/gnodev/pkg/packages/resolver.go b/contribs/gnodev/pkg/packages/resolver.go index 9ed9269b6d8..3f9a8eea085 100644 --- a/contribs/gnodev/pkg/packages/resolver.go +++ b/contribs/gnodev/pkg/packages/resolver.go @@ -199,10 +199,6 @@ func PackageCheckerMiddleware(logger *slog.Logger) MiddlewareHandler { return nil, err } - if err := pkg.Validate(); err != nil { - return nil, fmt.Errorf("invalid package %q: %w", path, err) - } - // Post-process each file in the package. for _, file := range pkg.Files { fname := file.Name diff --git a/gno.land/pkg/integration/pkgloader.go b/gno.land/pkg/integration/pkgloader.go index 3074a1abc8e..95a5dbe5881 100644 --- a/gno.land/pkg/integration/pkgloader.go +++ b/gno.land/pkg/integration/pkgloader.go @@ -84,14 +84,14 @@ func (pl *PkgsLoader) LoadPackages(creatorKey crypto.PrivKey, fee std.Fee, depos return txs, nil } -func (pl *PkgsLoader) LoadAllPackagesFromDir(path string) error { +func (pl *PkgsLoader) LoadAllPackagesFromDir(dir string) error { // list all packages from target path - pkgslist, err := gnomod.ListPkgs(path) + pkglist, err := gnolang.ReadPkgListFromDir(dir) if err != nil { return fmt.Errorf("listing gno packages from gnomod: %w", err) } - for _, pkg := range pkgslist { + for _, pkg := range pkglist { if !pl.exist(pkg) { pl.add(pkg) } @@ -115,11 +115,11 @@ func (pl *PkgsLoader) LoadPackage(modroot string, path, name string) error { if currentPkg.Name == "" { // Load `gno.mod` information - gnoModPath := filepath.Join(currentPkg.Dir, "gno.mod") - gm, err := gnomod.ParseGnoMod(gnoModPath) + gm, err := gnomod.ParseDir(currentPkg.Dir) if err != nil { - return fmt.Errorf("unable to load %q: %w", gnoModPath, err) + return fmt.Errorf("unable to load %q: %w", currentPkg.Dir, err) } + gm.Sanitize() // Override package info with mod infos diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index 08cf6d260ea..c0cca1318aa 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -1,6 +1,7 @@ package gnomod import ( + "errors" "fmt" "os" "path/filepath" @@ -13,6 +14,8 @@ import ( "golang.org/x/mod/module" ) +var ErrNoModFile = errors.New("gno.mod doesn't exist") + // ParseDir parses, validates and returns a gno.mod file located at dir or at // dir's parents. func ParseDir(dir string) (*File, error) { @@ -126,8 +129,8 @@ func ParseMemPackage(mpkg *std.MemPackage) (*File, error) { mf := mpkg.GetFile("gno.mod") if mf == nil { return nil, fmt.Errorf( - "gno.mod not in mem package %s (name=%s)", - mpkg.Path, mpkg.Name, + "gno.mod not in mem package %s (name=%s): %w", + mpkg.Path, mpkg.Name, os.ErrNotExist, ) } mod, err := ParseBytes(mf.Name, []byte(mf.Body)) From c3ed31ff4582bbba5ce21b64ed3c16a7709a8ef9 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Wed, 21 May 2025 10:08:54 +0200 Subject: [PATCH 65/83] fix: keeper load --- gno.land/pkg/sdk/vm/keeper.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 96380dd2754..9c9c8c95552 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -173,11 +173,14 @@ func (vm *VMKeeper) LoadStdlib(ctx sdk.Context, stdlibDir string) { func loadStdlib(store gno.Store, stdlibDir string) { stdlibInitList := stdlibs.InitOrder() for _, lib := range stdlibInitList { - if lib == "testing" { - // XXX: testing is skipped for now while it uses testing-only packages + parts := strings.Split(lib, "/") + if len(parts) > 0 && parts[0] == "testing" { + // XXX: testing and sub testing packages are skipped for + // now while it uses testing-only packages // like fmt and encoding/json continue } + loadStdlibPackage(lib, stdlibDir, store) } } From 371d6a2129eb3c78bb7ce9768c4e4249684e98c2 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 02:35:45 -0700 Subject: [PATCH 66/83] ... --- gnovm/cmd/gno/tool_fix.go | 2 +- gnovm/pkg/gnolang/machine.go | 3 +++ gnovm/pkg/test/imports.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index 0d6067f6dc1..cfa73427446 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -133,7 +133,7 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { bs, ts := test.StoreWithOptions( cmd.rootDir, goio.Discard, - test.StoreOptions{PreprocessOnly: true}, + test.StoreOptions{PreprocessOnly: true, FixFrom: gno.GnoVerMissing}, ) ppkgs := map[string]processedPackage{} diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 9be1c775974..ecc82243dfd 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -470,6 +470,9 @@ func (m *Machine) PreprocessFiles(pkgName, pkgPath string, fset *FileSet, save, } } pn := NewPackageNode(Name(pkgName), pkgPath, fset) + if fixFrom != "" { + pn.SetAttribute(ATTR_FIX_FROM, fixFrom) + } pv := pn.NewPackage() pb := pv.GetBlock(m.Store) m.SetActivePackage(pv) diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 4a32f09566c..9c91bcec806 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -76,7 +76,7 @@ func StoreWithOptions( if err != nil { panic(fmt.Errorf("test store parsing gno.mod: %w", err)) } - if mod.GetGno() == "0.0" { + if mod.GetGno() == gno.GnoVerMissing { // In order to translate into a newer Gno version with // the preprocessor make a slight modifications to the // AST. This needs to happen even for imports, because From 136e0fed446bf8cda562f69ab867741037273b59 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 03:33:29 -0700 Subject: [PATCH 67/83] ... --- gnovm/pkg/gnolang/nodes.go | 1 + gnovm/pkg/test/imports.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 333e31f6aeb..1c5a3d186d1 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -147,6 +147,7 @@ const ( ATTR_LAST_BLOCK_STMT GnoAttribute = "ATTR_LAST_BLOCK_STMT" ATTR_PACKAGE_REF GnoAttribute = "ATTR_PACKAGE_REF" ATTR_PACKAGE_DECL GnoAttribute = "ATTR_PACKAGE_DECL" + ATTR_FIX_FROM GnoAttribute = "ATTR_FIX_FROM" // gno fix this version. ) // Embedded in each Node. diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index 9c91bcec806..f77319ad04b 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -34,6 +34,9 @@ type StoreOptions struct { // When transpiling code in examples/ we use the test store. gno fix may need // gno.mod to not be auto-generated when importing from the test store. DoNotGenerateGnoMod bool + + // XXX + FixFrom string } // NOTE: this isn't safe, should only be used for testing. From 8fd6cb5f4c0e931387a07b928c9b9cb969e3db05 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 03:29:32 -0700 Subject: [PATCH 68/83] property sort normal/_test/filetests --- .../gno.land/r/demo/boards/z_5_filetest.gno | 4 +-- gnovm/cmd/gno/common.go | 9 ++++--- gnovm/pkg/gnolang/gotypecheck.go | 2 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 25 ++++++++++++------- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/examples/gno.land/r/demo/boards/z_5_filetest.gno b/examples/gno.land/r/demo/boards/z_5_filetest.gno index cb0a9c27800..9da23591384 100644 --- a/examples/gno.land/r/demo/boards/z_5_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_filetest.gno @@ -23,12 +23,12 @@ func init() { bid = cross(boards.CreateBoard)("test_board") cross(boards.CreateThread)(bid, "First Post (title)", "Body of the first post. (body)") pid = cross(boards.CreateThread)(bid, "Second Post (title)", "Body of the second post. (body)") - rid := cross(boards.CreateReply)(bid, pid, pid, "Reply of the second post") + _ = cross(boards.CreateReply)(bid, pid, pid, "Reply of the second post") } func main() { testing.SetRealm(std.NewUserRealm(std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"))) - rid2 := cross(boards.CreateReply)(bid, pid, pid, "Second reply of the second post\n") + _ = cross(boards.CreateReply)(bid, pid, pid, "Second reply of the second post\n") println(boards.Render("test_board/" + strconv.Itoa(int(pid)))) } diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index 2fe46c26c76..e1ea0667881 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -65,14 +65,15 @@ func sourceAndTestFileset(mpkg *std.MemPackage) ( continue // Skip empty files } all.AddFiles(n) - if string(n.PkgName) == mpkg.Name+"_test" { - // A xxx_file integration test is a package of its own. - _tests.AddFiles(n) - } else if strings.HasSuffix(mfile.Name, "_filetest.gno") { + if strings.HasSuffix(mfile.Name, "_filetest.gno") { // A _filetest.gno is a package of its own. ftset := &gno.FileSet{} ftset.AddFiles(n) ftests = append(ftests, ftset) + } else if strings.HasSuffix(mfile.Name, "_test.gno") && + strings.HasSuffix(string(n.PkgName), "_test") { + // A xxx_file integration test is a package of its own. + _tests.AddFiles(n) } else { // All normal package files and, // _test.gno files that aren't xxx_test. diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 71af7af87e4..32957ba8b4c 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -257,8 +257,8 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo */ continue } + // gofs2 (.gnobuiltins.gno), tgofs2 (*_testfile.gno) gofs2 = append(gofs2, tgofs2...) - _, _ = gimp.cfg.Check(tmpkg.Path, gofset2, gofs2, nil) /* NOTE: Uncomment to fail earlier. if len(gimp.errors) != numErrs { diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 94611dcd145..42f128def50 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -100,7 +100,8 @@ func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( // The *ast.File passed all filters. if strings.HasSuffix(file.Name, "_filetest.gno") { tgofs = append(tgofs, gof) - } else if strings.HasSuffix(gof.Name.String(), "_test") { + } else if strings.HasSuffix(file.Name, "_test.gno") && + strings.HasSuffix(gof.Name.String(), "_test") { if pmode == ParseModeIntegration { // never wanted these gofs. // (we do want other *_test.gno in gofs) @@ -323,6 +324,9 @@ func addXform2IfMatched( panic("oops, need to refactor xforms2 to allow multiple xforms per node?") } xforms2[gon] = xform1 + } else { + // for debugging: + // fmt.Println("not found", xform1) } } @@ -338,6 +342,10 @@ func addXform2IfMatched( // - fnames: file names (subset of mpkg) to transpile. // - xforms1: result of FindGno0p9Xforms(). func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames []Name, xforms1 map[string]struct{}) error { + // NOTE: The pkgPath may be different than mpkg.Path + // e.g. for filetests or xxx_test tests. + pkgPath := pn.PkgPath + // Return if gno.mod is current. var mod *gnomod.File var err error @@ -350,7 +358,7 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames [ } // Go parse and collect files from mpkg. - gofset := token.NewFileSet() + var gofset = token.NewFileSet() var errs error var xall int = 0 // number translated from part 1 for _, fname := range fnames { @@ -372,14 +380,14 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames [ continue } // Transpile Part 1: re-key xforms1 by ast.Node. - xnum, xforms2, err := transpileGno0p9_part1(mpkg.Path, gofset, mfile.Name, gof, xforms1) + xnum, xforms2, err := transpileGno0p9_part1(pkgPath, gofset, mfile.Name, gof, xforms1) if err != nil { errs = multierr.Append(errs, err) continue } xall += xnum // Transpile Part 2: main Go AST transform for Gno 0.9. - if err := transpileGno0p9_part2(mpkg.Path, gofset, mfile.Name, gof, xforms2); err != nil { + if err := transpileGno0p9_part2(pkgPath, gofset, mfile.Name, gof, xforms2); err != nil { errs = multierr.Append(errs, err) continue } @@ -414,10 +422,6 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames [ func transpileGno0p9_part1(pkgPath string, gofs *token.FileSet, fname string, gof *ast.File, xforms1 map[string]struct{}) (xfound int, xforms2 map[ast.Node]string, err error) { xforms2 = make(map[ast.Node]string, len(xforms1)) - if len(xforms1) == 0 { - return 0, nil, nil // nothing to translate. - } - astutil.Apply(gof, func(c *astutil.Cursor) bool { // Main switch on c.Node() type. switch gon := c.Node().(type) { @@ -469,7 +473,10 @@ XFORMS1_LOOP: continue XFORMS1_LOOP } } - fmt.Println("xform2 item not found for xform1:", xform1) + fmt.Println("xform2 item not found for xform1:", xform1, len(xforms2)) + for _, xform2 := range xforms2 { + fmt.Println("xform2:", xform2) + } mismatch = true } if mismatch { From 28f63824fd456f927f5254640277b8d21427339b Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 04:49:55 -0700 Subject: [PATCH 69/83] type-check fix examples more --- examples/gno.land/r/demo/tests/z2_filetest.gno | 4 ++-- .../gno.land/r/gnoland/faucet/z3_filetest.gno | 2 +- .../r/gnoland/users/v1/z_0_prop1_filetest.gno | 4 ++-- .../gno.land/r/gnoland/users/z_0_filetest.gno | 4 ++-- .../gnoland/valopers_proposal/proposal_test.gno | 10 +++------- examples/gno.land/r/leon/hor/hof_test.gno | 16 ++++++++-------- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/examples/gno.land/r/demo/tests/z2_filetest.gno b/examples/gno.land/r/demo/tests/z2_filetest.gno index 94e9b51ee94..549a5e2bbb8 100644 --- a/examples/gno.land/r/demo/tests/z2_filetest.gno +++ b/examples/gno.land/r/demo/tests/z2_filetest.gno @@ -12,8 +12,8 @@ import ( // When 2 or more realms in the frames, PreviousRealm returns the second to last func main() { var ( - eoa = testutils.TestAddress("someone") - rTestsAddr = std.DerivePkgAddr("gno.land/r/demo/tests") + eoa = testutils.TestAddress("someone") + _ = std.DerivePkgAddr("gno.land/r/demo/tests") ) testing.SetOriginCaller(eoa) println("tests.GetPreviousRealm().Address(): ", cross(tests.GetPreviousRealm)().Address()) diff --git a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno index f4c55bbc928..6140bac7f03 100644 --- a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno @@ -21,7 +21,7 @@ func main() { controlleraddr1 = testutils.TestAddress("controller1") controlleraddr2 = testutils.TestAddress("controller2") testaddr1 = testutils.TestAddress("test1") - testaddr2 = testutils.TestAddress("test2") + _ = testutils.TestAddress("test2") ) testing.SetRealm(std.NewUserRealm(adminaddr)) err := cross(faucet.AdminAddController)(controlleraddr1) diff --git a/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno b/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno index c0c98b7da89..40a6ba1feb6 100644 --- a/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno +++ b/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/p/demo/testutils" users "gno.land/r/gnoland/users/v1" "gno.land/r/gov/dao" - "gno.land/r/gov/dao/v3/init" + ini "gno.land/r/gov/dao/v3/init" susers "gno.land/r/sys/users" ) @@ -17,7 +17,7 @@ import ( var c std.Address = std.OriginCaller() func init() { - init.InitWithUsers(c) + ini.InitWithUsers(c) alice := testutils.TestAddress("alice") diff --git a/examples/gno.land/r/gnoland/users/z_0_filetest.gno b/examples/gno.land/r/gnoland/users/z_0_filetest.gno index ff4dfaeb9e1..c376d3b4f9c 100644 --- a/examples/gno.land/r/gnoland/users/z_0_filetest.gno +++ b/examples/gno.land/r/gnoland/users/z_0_filetest.gno @@ -7,7 +7,7 @@ import ( "gno.land/p/demo/testutils" "gno.land/r/gnoland/users" "gno.land/r/gov/dao" - "gno.land/r/gov/dao/v3/init" + ini "gno.land/r/gov/dao/v3/init" ) var ( @@ -17,7 +17,7 @@ var ( func init() { testing.SetRealm(std.NewUserRealm(alice)) c := std.OriginCaller() - init.InitWithUsers(c) + ini.InitWithUsers(c) pReq := users.ProposeNewRelease("gno.land/r/gnoland/users/v2", "This is a note!") diff --git a/examples/gno.land/r/gnoland/valopers_proposal/proposal_test.gno b/examples/gno.land/r/gnoland/valopers_proposal/proposal_test.gno index aab16462f5d..e01df071dde 100644 --- a/examples/gno.land/r/gnoland/valopers_proposal/proposal_test.gno +++ b/examples/gno.land/r/gnoland/valopers_proposal/proposal_test.gno @@ -42,10 +42,8 @@ func TestValopers_ProposeNewValidator(t *testing.T) { cross(valopers.UpdateKeepRunning)(g1user, false) }) - var valoper valopers.Valoper - urequire.NotPanics(t, func() { - valoper = valopers.GetByAddr(g1user) + valopers.GetByAddr(g1user) }) // Send coins to be able to make a proposal @@ -79,7 +77,7 @@ func TestValopers_ProposeNewValidator(t *testing.T) { urequire.NotPanics(t, func() { pr := NewValidatorProposalRequest(g1user) - pid := cross(dao.MustCreateProposal)(pr) + pid = cross(dao.MustCreateProposal)(pr) }) proposal, err := cross(dao.GetProposal)(pid) // index starts from 0 @@ -99,10 +97,8 @@ func TestValopers_ProposeNewValidator(t *testing.T) { // Send coins to be able to register a valoper testing.SetOriginSend(std.Coins{std.NewCoin("ugnot", registerMinFee)}) - var valoper valopers.Valoper - urequire.NotPanics(t, func() { - valoper = valopers.GetByAddr(g1user) + valopers.GetByAddr(g1user) }) urequire.NotPanics(t, func() { diff --git a/examples/gno.land/r/leon/hor/hof_test.gno b/examples/gno.land/r/leon/hor/hof_test.gno index 54d2a016f70..a7f4bbc4b81 100644 --- a/examples/gno.land/r/leon/hor/hof_test.gno +++ b/examples/gno.land/r/leon/hor/hof_test.gno @@ -125,7 +125,7 @@ func TestDelete(t *testing.T) { }) i, _ := exhibition.items.Get(rlmPath) - id := i.(*Item).id + _ = i.(*Item).id uassert.NotPanics(t, func() { cross(Delete)(rlmPath) @@ -137,7 +137,7 @@ func TestDelete(t *testing.T) { func itemExists(t *testing.T, rlmPath string) bool { t.Helper() - i, ok1 := exhibition.items.Get(rlmPath) + _, ok1 := exhibition.items.Get(rlmPath) return ok1 } @@ -210,11 +210,11 @@ func TestSortByUpvote(t *testing.T) { cross(Upvote)(rlmPath5) // We are displaying data in reverse order in render, so items should be sorted in reverse order - firstKey, firstRawValue := exhibition.itemsSortedByUpvotes.GetByIndex(0) + _, firstRawValue := exhibition.itemsSortedByUpvotes.GetByIndex(0) firstValue := firstRawValue.(*Item) uassert.Equal(t, firstValue.pkgpath, rlmPath3) - secondKey, secondRawValue := exhibition.itemsSortedByUpvotes.GetByIndex(1) + _, secondRawValue := exhibition.itemsSortedByUpvotes.GetByIndex(1) secondValue := secondRawValue.(*Item) uassert.Equal(t, secondValue.pkgpath, rlmPath4) } @@ -268,13 +268,13 @@ func TestSortByDownvote(t *testing.T) { cross(Downvote)(rlmPath5) // We are dispalying data is reverse order in render, so items should be sorted in reverse order - firstKey, firstRawValue := exhibition.itemsSortedByDownvotes.GetByIndex(0) + _, firstRawValue := exhibition.itemsSortedByDownvotes.GetByIndex(0) firstValue := firstRawValue.(*Item) uassert.Equal(t, firstValue.pkgpath, rlmPath3) - secondKey, secondRawValue := exhibition.itemsSortedByDownvotes.GetByIndex(1) + _, secondRawValue := exhibition.itemsSortedByDownvotes.GetByIndex(1) secondValue := secondRawValue.(*Item) @@ -313,13 +313,13 @@ func TestSortByCreation(t *testing.T) { cross(Register)(validTitle, validDesc) // We are dispalying data is reverse order in render, so items should be sorted in reverse order - firstKey, firstRawValue := exhibition.itemsSortedByCreation.GetByIndex(0) + _, firstRawValue := exhibition.itemsSortedByCreation.GetByIndex(0) firstValue := firstRawValue.(*Item) uassert.Equal(t, firstValue.pkgpath, rlmPath3) - secondKey, secondRawValue := exhibition.itemsSortedByCreation.GetByIndex(1) + _, secondRawValue := exhibition.itemsSortedByCreation.GetByIndex(1) secondValue := secondRawValue.(*Item) From 76fb198b7ef229c82bb8f3f7e66edd2a39caefdd Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 04:57:24 -0700 Subject: [PATCH 70/83] fix one r/leon/hor test --- examples/gno.land/r/leon/hor/datasource_test.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/r/leon/hor/datasource_test.gno b/examples/gno.land/r/leon/hor/datasource_test.gno index 207314db81b..5371ba3f7c5 100644 --- a/examples/gno.land/r/leon/hor/datasource_test.gno +++ b/examples/gno.land/r/leon/hor/datasource_test.gno @@ -155,7 +155,7 @@ func TestItemRecord(t *testing.T) { wantContent := `### [Test Realm](/r/demo/test) This is a test realm in the Hall of Fame -by demo +by [@demo](/r/gnoland/users/v1:demo) Submitted at Block #42 From 54bc6eb894be46877e88029ae9ee8f8c8cc3a48a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 21 May 2025 17:06:16 +0300 Subject: [PATCH 71/83] fix import name issue --- examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno | 4 ++-- examples/gno.land/r/gnoland/users/v1/z_1_prop2_filetest.gno | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno b/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno index 40a6ba1feb6..7ba337f2eb7 100644 --- a/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno +++ b/examples/gno.land/r/gnoland/users/v1/z_0_prop1_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/p/demo/testutils" users "gno.land/r/gnoland/users/v1" "gno.land/r/gov/dao" - ini "gno.land/r/gov/dao/v3/init" + daov3init "gno.land/r/gov/dao/v3/init" susers "gno.land/r/sys/users" ) @@ -17,7 +17,7 @@ import ( var c std.Address = std.OriginCaller() func init() { - ini.InitWithUsers(c) + daov3init.InitWithUsers(c) alice := testutils.TestAddress("alice") diff --git a/examples/gno.land/r/gnoland/users/v1/z_1_prop2_filetest.gno b/examples/gno.land/r/gnoland/users/v1/z_1_prop2_filetest.gno index e6bb2e10df4..95db1e5a1cf 100644 --- a/examples/gno.land/r/gnoland/users/v1/z_1_prop2_filetest.gno +++ b/examples/gno.land/r/gnoland/users/v1/z_1_prop2_filetest.gno @@ -9,7 +9,7 @@ import ( "gno.land/p/demo/testutils" users "gno.land/r/gnoland/users/v1" "gno.land/r/gov/dao" - "gno.land/r/gov/dao/v3/init" + daov3init "gno.land/r/gov/dao/v3/init" susers "gno.land/r/sys/users" ) @@ -18,7 +18,7 @@ import ( var c std.Address = std.OriginCaller() func init() { - init.InitWithUsers(c) + daov3init.InitWithUsers(c) alice := testutils.TestAddress("alice") From 3becb1c92897797c4060041b18271a3f9a08d4ed Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 21 May 2025 18:02:43 +0200 Subject: [PATCH 72/83] chore(examples): add 'make fix' Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/Makefile b/examples/Makefile index 2c2c03f5e32..9e95cac6399 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -44,6 +44,10 @@ test.fast: lint: go run ../gnovm/cmd/gno lint -v . +.PHONY: fix +fix: + go run ../gnovm/cmd/gno fix -v . + .PHONY: test.sync test.sync: go run ../gnovm/cmd/gno test -v --update-golden-tests ./... From 6b551a464090af713cb385740634fde860192ece Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Wed, 21 May 2025 18:22:39 +0200 Subject: [PATCH 73/83] p/*_test.gno can import r/ Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/pkg/gnolang/helpers.go | 4 ++++ gnovm/pkg/gnolang/preprocess.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/helpers.go b/gnovm/pkg/gnolang/helpers.go index 122e8d052d2..51a1298ea39 100644 --- a/gnovm/pkg/gnolang/helpers.go +++ b/gnovm/pkg/gnolang/helpers.go @@ -84,6 +84,10 @@ func IsStdlib(s string) bool { return strings.IndexByte(s[:idx+1], '.') < 0 } +func IsTestFile(file string) bool { + return strings.HasSuffix(file, "_test.gno") || strings.HasSuffix(file, "_filetest.gno") +} + // ---------------------------------------- // AST Construction (Expr) // These are copied over from go-amino-x, but produces Gno ASTs. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 712e72eb931..a2531540a39 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -4329,7 +4329,7 @@ func tryPredefine(store Store, pkg *PackageNode, last BlockNode, d Decl, stack [ // NOTE: imports from "pure packages" are actually sometimes // allowed, most notably filetests. - if IsPPackagePath(pkg.PkgPath) && IsRealmPath(d.PkgPath) { + if IsPPackagePath(pkg.PkgPath) && IsRealmPath(d.PkgPath) && !IsTestFile(last.GetLocation().File) { panic(fmt.Sprintf("pure package path %q cannot import realm path %q", pkg.PkgPath, d.PkgPath)) } From 09fa106267adce10eb465c435a13a13beb143aeb Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 21 May 2025 18:57:47 -0700 Subject: [PATCH 74/83] validate mempackage --- gnovm/cmd/benchops/run.go | 10 +- gnovm/cmd/gno/common.go | 33 ++--- gnovm/cmd/gno/run.go | 18 +-- gnovm/cmd/gno/tool_fix.go | 106 +++++++++++---- gnovm/pkg/doc/json_doc.go | 6 +- gnovm/pkg/doc/json_doc_test.go | 4 +- gnovm/pkg/doc/pkg.go | 18 +-- gnovm/pkg/gnolang/files_test.go | 33 ++++- gnovm/pkg/gnolang/machine.go | 43 +++--- gnovm/pkg/gnolang/mempackage.go | 162 +++++++++++++++++++++++ gnovm/pkg/gnolang/nodes.go | 128 +++++++++--------- gnovm/pkg/gnolang/store.go | 7 +- gnovm/pkg/gnolang/store_test.go | 2 +- gnovm/pkg/gnolang/transpile_gno0p9.go | 7 +- gnovm/pkg/gnolang/validate_mempackage.go | 38 ------ gnovm/pkg/test/filetest.go | 10 +- gnovm/pkg/test/imports.go | 4 +- tm2/pkg/std/memfile.go | 33 ++++- 18 files changed, 446 insertions(+), 216 deletions(-) create mode 100644 gnovm/pkg/gnolang/mempackage.go delete mode 100644 gnovm/pkg/gnolang/validate_mempackage.go diff --git a/gnovm/cmd/benchops/run.go b/gnovm/cmd/benchops/run.go index e63bbcd5e10..5f72bcb18e3 100644 --- a/gnovm/cmd/benchops/run.go +++ b/gnovm/cmd/benchops/run.go @@ -103,10 +103,10 @@ func addPackage(gstore gno.Store, dir string, pkgPath string) *gno.PackageValue }) defer m.Release() - memPkg := gno.MustReadMemPackage(dir, pkgPath) + mpkg := gno.MustReadMemPackage(dir, pkgPath) // pare the file, create pn, pv and save the values in m.store - _, pv := m.RunMemPackage(memPkg, true) + _, pv := m.RunMemPackage(mpkg, true) return pv } @@ -122,8 +122,8 @@ func loadStdlibs(bstore BenchStore) { return nil, nil } - memPkg := gno.MustReadMemPackage(stdlibPath, pkgPath) - if memPkg.IsEmpty() { + mpkg := gno.MustReadMemPackage(stdlibPath, pkgPath) + if mpkg.IsEmpty() { // no gno files are present, skip this package return nil, nil } @@ -135,7 +135,7 @@ func loadStdlibs(bstore BenchStore) { Store: newStore, }) defer m2.Release() - return m2.RunMemPackage(memPkg, true) + return m2.RunMemPackage(mpkg, true) } bstore.gnoStore.SetPackageGetter(getPackage) diff --git a/gnovm/cmd/gno/common.go b/gnovm/cmd/gno/common.go index e1ea0667881..5eeb02ef39a 100644 --- a/gnovm/cmd/gno/common.go +++ b/gnovm/cmd/gno/common.go @@ -234,21 +234,24 @@ func printError(w io.WriteCloser, dir, pkgPath string, err error) { } func catchPanic(dir, pkgPath string, stderr io.WriteCloser, action func()) (didPanic bool) { - // Uncomment for debugging. - defer func() { - // Errors catched here mostly come from: - // gnovm/pkg/gnolang/preprocess.go - r := recover() - if r == nil { - return - } - didPanic = true - if err, ok := r.(error); ok { - printError(stderr, dir, pkgPath, err) - } else { - panic(r) - } - }() + // If this gets out of hand (e.g. with nested catchPanic with need for + // selective catching) then pass in a bool instead. + if os.Getenv("DEBUG_PANIC") != "1" { + defer func() { + // Errors catched here mostly come from: + // gnovm/pkg/gnolang/preprocess.go + r := recover() + if r == nil { + return + } + didPanic = true + if err, ok := r.(error); ok { + printError(stderr, dir, pkgPath, err) + } else { + panic(r) + } + }() + } action() return diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index bde398586e6..ebda752d649 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -17,7 +17,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -type runCfg struct { +type runCmd struct { verbose bool rootDir string expr string @@ -25,8 +25,8 @@ type runCfg struct { debugAddr string } -func newRunCmd(io commands.IO) *commands.Command { - cfg := &runCfg{} +func newRunCmd(cio commands.IO) *commands.Command { + cfg := &runCmd{} return commands.NewCommand( commands.Metadata{ @@ -36,12 +36,12 @@ func newRunCmd(io commands.IO) *commands.Command { }, cfg, func(_ context.Context, args []string) error { - return execRun(cfg, args, io) + return execRun(cfg, args, cio) }, ) } -func (c *runCfg) RegisterFlags(fs *flag.FlagSet) { +func (c *runCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar( &c.verbose, "v", @@ -78,7 +78,7 @@ func (c *runCfg) RegisterFlags(fs *flag.FlagSet) { ) } -func execRun(cfg *runCfg, args []string, io commands.IO) error { +func execRun(cfg *runCmd, args []string, cio commands.IO) error { if len(args) == 0 { return flag.ErrHelp } @@ -87,9 +87,9 @@ func execRun(cfg *runCfg, args []string, io commands.IO) error { cfg.rootDir = gnoenv.RootDir() } - stdin := io.In() - stdout := io.Out() - stderr := io.Err() + stdin := cio.In() + stdout := cio.Out() + stderr := cio.Err() // init store and machine output := test.OutputWithError(stdout, stderr) diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index cfa73427446..091ed76284a 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "errors" "flag" @@ -18,6 +19,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/test" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/std" ) /* @@ -84,13 +86,14 @@ Also refer to the [Lint and Transpile ADR](./adr/pr4264_lint_transpile.md). */ type fixCmd struct { - verbose bool - rootDir string + verbose bool + rootDir string + filetestsOnly bool // min_confidence: minimum confidence of a problem to print it // (default 0.8) auto-fix: apply suggested fixes automatically. } -func newFixCmd(io commands.IO) *commands.Command { +func newFixCmd(cio commands.IO) *commands.Command { cmd := &fixCmd{} return commands.NewCommand( @@ -101,7 +104,7 @@ func newFixCmd(io commands.IO) *commands.Command { }, cmd, func(_ context.Context, args []string) error { - return execFix(cmd, args, io) + return execFix(cmd, args, cio) }, ) } @@ -111,25 +114,32 @@ func (c *fixCmd) RegisterFlags(fs *flag.FlagSet) { fs.BoolVar(&c.verbose, "v", false, "verbose output when fixning") fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)") + fs.BoolVar(&c.filetestsOnly, "only-filetests", false, "dir only contains filetests. not recursive.") } -func execFix(cmd *fixCmd, args []string, io commands.IO) error { +func execFix(cmd *fixCmd, args []string, cio commands.IO) error { // Show a help message by default. if len(args) == 0 { return flag.ErrHelp } - // Guess opts.RootDir. + // Guess cmd.RootDir. if cmd.rootDir == "" { cmd.rootDir = gnoenv.RootDir() } - dirs, err := gnoPackagesFromArgsRecursively(args) - if err != nil { - return fmt.Errorf("list packages from args: %w", err) - } + var dirs []string = nil + var hasError bool = false + var err error = nil - hasError := false + if cmd.filetestsOnly { + dirs = append([]string(nil), args...) + } else { + dirs, err = gnoPackagesFromArgsRecursively(args) + if err != nil { + return fmt.Errorf("list packages from args: %w", err) + } + } bs, ts := test.StoreWithOptions( cmd.rootDir, goio.Discard, @@ -138,13 +148,13 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { ppkgs := map[string]processedPackage{} if cmd.verbose { - io.ErrPrintfln("flinting directories: %v", dirs) + cio.ErrPrintfln("flinting directories: %v", dirs) } //---------------------------------------- // FIX STAGE 1: Type-check and lint. for _, dir := range dirs { if cmd.verbose { - io.ErrPrintfln("fixing %q", dir) + cio.ErrPrintfln("fixing %q", dir) } // Only supports directories. @@ -164,6 +174,19 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { if err != nil { panic(fmt.Errorf("unexpected panic parsing default gno.mod bytes: %w", err)) } + } else { + switch mod.GetGno() { + case gno.GnoVerLatest: + if cmd.verbose { + cio.ErrPrintfln("%s: module is up to date, skipping fix", dir) + } + continue // nothing to do. + case gno.GnoVerMissing: + // good, fix it. + default: + cio.ErrPrintfln("%s: unrecognized gno.mod version %q, skipping fix", dir, mod.GetGno()) + continue // skip it. + } } if err != nil { issue := gnoIssue{ @@ -172,10 +195,14 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { Location: fpath, Msg: err.Error(), } - io.ErrPrintln(issue) + cio.ErrPrintln(issue) hasError = true return commands.ExitCodeError(1) } + if mod.Draft { + cio.ErrPrintfln("%s: module is draft, skipping fix", dir) + continue + } // See adr/pr4264_fix_transpile.md // FIX STEP 1: ReadMemPackage() @@ -183,20 +210,25 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { pkgPath, _ := determinePkgPath(mod, dir, cmd.rootDir) mpkg, err := gno.ReadMemPackage(dir, pkgPath) if err != nil { - printError(io.Err(), dir, pkgPath, err) + printError(cio.Err(), dir, pkgPath, err) hasError = true continue } + // Filter out filetests that fail type-check. + if cmd.filetestsOnly { + filterInvalidFiletests(cio, mpkg) + } + // Perform imports using the parent store. if err := test.LoadImports(ts, mpkg); err != nil { - printError(io.Err(), dir, pkgPath, err) + printError(cio.Err(), dir, pkgPath, err) hasError = true continue } // Handle runtime errors - didPanic := catchPanic(dir, pkgPath, io.Err(), func() { + didPanic := catchPanic(dir, pkgPath, cio.Err(), func() { // Wrap in cache wrap so execution of the fixer // doesn't impact other packages. cw := bs.CacheWrap() @@ -218,15 +250,12 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - if !mod.Draft { - _, gofset, gofs, _gofs, tgofs, errs = lintTypeCheck(io, dir, mpkg, gs) - if errs != nil { - // io.ErrPrintln(errs) already printed. - hasError = true - return - } - } else if cmd.verbose { - io.ErrPrintfln("%s: module is draft, skipping type check", dir) + _, gofset, gofs, _gofs, tgofs, errs = + lintTypeCheck(cio, dir, mpkg, gs) // , false) + if errs != nil { + // cio.ErrPrintln(errs) already printed. + hasError = true + return } // FIX STEP 4: Prepare*() @@ -239,14 +268,14 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { allgofs = append(allgofs, tgofs...) errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) if errs != nil { - io.ErrPrintln(errs) + cio.ErrPrintln(errs) hasError = true return // Prepare must succeed. } // FIX STEP 5: re-parse // Gno parse source fileset and test filesets. - _, fset, _tests, ftests := sourceAndTestFileset(mpkg) + _, fset, _tests, ftests := sourceAndTestFileset(mpkg) // , cmd.filetestsOnly) { // FIX STEP 6: PreprocessFiles() @@ -300,7 +329,7 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { pkgPath := fmt.Sprintf("%s_filetest%d", mpkg.Path, i) pkgPath, err = parsePkgPathDirective(mfile.Body, pkgPath) if err != nil { - io.ErrPrintln(err) + cio.ErrPrintln(err) hasError = true continue } @@ -404,3 +433,22 @@ func execFix(cmd *fixCmd, args []string, io commands.IO) error { return nil } + +// When in filetestsOnly mode, filter out files that are known to have a +// type-check error. These files will be deleted from the mpkg. +// They are only deleted from mpkg; gno fix will not affect the files +// already on disk. +func filterInvalidFiletests(cio commands.IO, mpkg *std.MemPackage) { + for _, mfile := range mpkg.Files { + dirs, err := test.ParseDirectives(bytes.NewReader([]byte(mfile.Body))) + if err != nil { + panic(fmt.Errorf("error parsing directives: %w", err)) + } + tcErr := dirs.FirstDefault(test.DirectiveTypeCheckError, "") + if tcErr != "" { + cio.Printfln("skipping invalid filetest %q", mfile.Name) + mpkg.DeleteFile(mfile.Name) + continue + } + } +} diff --git a/gnovm/pkg/doc/json_doc.go b/gnovm/pkg/doc/json_doc.go index 149df178702..b6daf5e1e99 100644 --- a/gnovm/pkg/doc/json_doc.go +++ b/gnovm/pkg/doc/json_doc.go @@ -59,9 +59,9 @@ type JSONType struct { Doc string `json:"doc"` // markdown } -// NewDocumentableFromMemPkg gets the pkgData from memPkg and returns a Documentable -func NewDocumentableFromMemPkg(memPkg *std.MemPackage, unexported bool, symbol, accessible string) (*Documentable, error) { - pd, err := newPkgDataFromMemPkg(memPkg, unexported) +// NewDocumentableFromMemPkg gets the pkgData from mpkg and returns a Documentable +func NewDocumentableFromMemPkg(mpkg *std.MemPackage, unexported bool, symbol, accessible string) (*Documentable, error) { + pd, err := newPkgDataFromMemPkg(mpkg, unexported) if err != nil { return nil, err } diff --git a/gnovm/pkg/doc/json_doc_test.go b/gnovm/pkg/doc/json_doc_test.go index 7cdfccf0084..806dc10c664 100644 --- a/gnovm/pkg/doc/json_doc_test.go +++ b/gnovm/pkg/doc/json_doc_test.go @@ -192,9 +192,9 @@ func TestJSONDocumentation(t *testing.T) { } // Get the JSONDocumentation similar to VMKeeper.QueryDoc - memPkg, err := gnolang.ReadMemPackage(dir, pkgPath) + mpkg, err := gnolang.ReadMemPackage(dir, pkgPath) require.NoError(t, err) - d, err := NewDocumentableFromMemPkg(memPkg, true, "", "") + d, err := NewDocumentableFromMemPkg(mpkg, true, "", "") require.NoError(t, err) jdoc, err := d.WriteJSONDocumentation() require.NoError(t, err) diff --git a/gnovm/pkg/doc/pkg.go b/gnovm/pkg/doc/pkg.go index caab3624deb..76b89bdc4ca 100644 --- a/gnovm/pkg/doc/pkg.go +++ b/gnovm/pkg/doc/pkg.go @@ -38,22 +38,22 @@ type symbolData struct { } func newPkgData(dir bfsDir, unexported bool) (*pkgData, error) { - memPkg, err := gnolang.ReadMemPackage(dir.dir, dir.importPath) + mpkg, err := gnolang.ReadMemPackage(dir.dir, dir.importPath) if err != nil { return nil, fmt.Errorf("commands/doc: read files %q: %w", dir.dir, err) } - return newPkgDataFromMemPkg(memPkg, unexported) + return newPkgDataFromMemPkg(mpkg, unexported) } -func newPkgDataFromMemPkg(memPkg *std.MemPackage, unexported bool) (*pkgData, error) { +func newPkgDataFromMemPkg(mpkg *std.MemPackage, unexported bool) (*pkgData, error) { pkg := &pkgData{ dir: bfsDir{ - importPath: memPkg.Name, - dir: memPkg.Path, + importPath: mpkg.Name, + dir: mpkg.Path, }, fset: token.NewFileSet(), } - for _, file := range memPkg.Files { + for _, file := range mpkg.Files { n := file.Name // Ignore files with prefix . or _ like go tools do. // Ignore _filetest.gno, but not _test.gno, as we use those to compute @@ -66,18 +66,18 @@ func newPkgDataFromMemPkg(memPkg *std.MemPackage, unexported bool) (*pkgData, er } err := pkg.parseFile(n, file.Body, unexported) if err != nil { - fullPath := filepath.Join(memPkg.Path, n) + fullPath := filepath.Join(mpkg.Path, n) return nil, fmt.Errorf("commands/doc: parse file %q: %w", fullPath, err) } } if len(pkg.files) == 0 { - return nil, fmt.Errorf("commands/doc: no valid gno files in %q", memPkg.Path) + return nil, fmt.Errorf("commands/doc: no valid gno files in %q", mpkg.Path) } pkgName := pkg.files[0].Name.Name for _, file := range pkg.files[1:] { if file.Name.Name != pkgName { - return nil, fmt.Errorf("commands/doc: multiple packages (%q / %q) in dir %q", pkgName, file.Name.Name, memPkg.Path) + return nil, fmt.Errorf("commands/doc: multiple packages (%q / %q) in dir %q", pkgName, file.Name.Name, mpkg.Path) } } pkg.name = pkgName diff --git a/gnovm/pkg/gnolang/files_test.go b/gnovm/pkg/gnolang/files_test.go index 2878965210e..af1e4da705c 100644 --- a/gnovm/pkg/gnolang/files_test.go +++ b/gnovm/pkg/gnolang/files_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/fs" + "io/ioutil" "os" "path/filepath" "strings" @@ -152,10 +153,28 @@ func TestStdlibs(t *testing.T) { } fp := filepath.Join(dir, path) - memPkg := gnolang.MustReadMemPackage(fp, path) - t.Run(strings.ReplaceAll(memPkg.Path, "/", "-"), func(t *testing.T) { + + // Exclude empty directories. + files, err := ioutil.ReadDir(fp) + hasFiles := false + if err != nil { + return err + } + for _, file := range files { + if !file.IsDir() && + strings.HasSuffix(file.Name(), ".gno") { + hasFiles = true + } + } + if !hasFiles { + return nil + } + + // Read and run tests. + mpkg := gnolang.MustReadMemPackage(fp, path) + t.Run(strings.ReplaceAll(mpkg.Path, "/", "-"), func(t *testing.T) { capture, opts := sharedCapture, sharedOpts - switch memPkg.Path { + switch mpkg.Path { // Excluded in short case "bufio", @@ -179,7 +198,7 @@ func TestStdlibs(t *testing.T) { capture.Reset() } - err := test.Test(memPkg, "", opts) + err := test.Test(mpkg, "", opts) if !testing.Verbose() { t.Log(capture.String()) } @@ -210,13 +229,13 @@ func TestStdlibs(t *testing.T) { } fp := filepath.Join(testDir, path) - memPkg := gnolang.MustReadMemPackage(fp, path) - t.Run("test-"+strings.ReplaceAll(memPkg.Path, "/", "-"), func(t *testing.T) { + mpkg := gnolang.MustReadMemPackage(fp, path) + t.Run("test-"+strings.ReplaceAll(mpkg.Path, "/", "-"), func(t *testing.T) { if sharedCapture != nil { sharedCapture.Reset() } - err := test.Test(memPkg, "", sharedOpts) + err := test.Test(mpkg, "", sharedOpts) if !testing.Verbose() { t.Log(sharedCapture.String()) } diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index ecc82243dfd..857493aa13d 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -196,9 +196,9 @@ func (m *Machine) SetActivePackage(pv *PackageValue) { // to support cases of stdlibs processed through [RunMemPackagesWithOverrides]. func (m *Machine) PreprocessAllFilesAndSaveBlockNodes() { ch := m.Store.IterMemPackage() - for memPkg := range ch { - fset := ParseMemPackage(memPkg) - pn := NewPackageNode(Name(memPkg.Name), memPkg.Path, fset) + for mpkg := range ch { + fset := ParseMemPackage(mpkg) + pn := NewPackageNode(Name(mpkg.Name), mpkg.Path, fset) m.Store.SetBlockNode(pn) PredefineFileSet(m.Store, pn, fset) for _, fn := range fset.Files { @@ -224,40 +224,43 @@ func (m *Machine) PreprocessAllFilesAndSaveBlockNodes() { //---------------------------------------- // top level Run* methods. -// Sorts and parses files, sets the package if doesn't exist, runs files, saves mempkg -// and corresponding package node, package value, and types to store. Save -// is set to false for tests where package values may be native. -func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { +// Sorts the package, then sets the package if doesn't exist, runs files, saves +// mpkg and corresponding package node, package value, and types to store. Save +// is set to false for tests where package values may be native. NOTE: Does +// not validate the mpkg. Caller must validate the mpkg before calling. +func (m *Machine) RunMemPackage(mpkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { if bm.OpsEnabled || bm.StorageEnabled { bm.InitMeasure() } if bm.StorageEnabled { defer bm.FinishStore() } - memPkg.Sort() - return m.runMemPackage(memPkg, save, false) + return m.runMemPackage(mpkg, save, false) } // RunMemPackageWithOverrides works as [RunMemPackage], however after parsing, -// declarations are filtered removing duplicate declarations. -// To control which declaration overrides which, use [ReadMemPackageFromList], -// putting the overrides at the top of the list. -func (m *Machine) RunMemPackageWithOverrides(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { - return m.runMemPackage(memPkg, save, true) +// declarations are filtered removing duplicate declarations. To control which +// declaration overrides which, use [ReadMemPackageFromList], putting the +// overrides at the top of the list. NOTE: Does not validate the mpkg, except +// when saving validates with type MemPackageTypeAny. +func (m *Machine) RunMemPackageWithOverrides(mpkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { + return m.runMemPackage(mpkg, save, true) } -func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { +func (m *Machine) runMemPackage(mpkg *std.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { + // sort mpkg. + mpkg.Sort() // parse files. - files := ParseMemPackage(memPkg) + files := ParseMemPackage(mpkg) // make and set package if doesn't exist. pn := (*PackageNode)(nil) pv := (*PackageValue)(nil) - if m.Package != nil && m.Package.PkgPath == memPkg.Path { + if m.Package != nil && m.Package.PkgPath == mpkg.Path { pv = m.Package - loc := PackageNodeLocation(memPkg.Path) + loc := PackageNodeLocation(mpkg.Path) pn = m.Store.GetBlockNode(loc).(*PackageNode) } else { - pn = NewPackageNode(Name(memPkg.Name), memPkg.Path, &FileSet{}) + pn = NewPackageNode(Name(mpkg.Name), mpkg.Path, &FileSet{}) pv = pn.NewPackage() m.Store.SetBlockNode(pn) m.Store.SetCachePackage(pv) @@ -281,7 +284,7 @@ func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (* if save { m.resavePackageValues(throwaway) // store mempackage - m.Store.AddMemPackage(memPkg) + m.Store.AddMemPackage(mpkg, MemPackageTypeAny) if throwaway != nil { m.Realm = nil } diff --git a/gnovm/pkg/gnolang/mempackage.go b/gnovm/pkg/gnolang/mempackage.go new file mode 100644 index 00000000000..d8f8594c6de --- /dev/null +++ b/gnovm/pkg/gnolang/mempackage.go @@ -0,0 +1,162 @@ +package gnolang + +import ( + "fmt" + "path" + "regexp" + "slices" + "strings" + + "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/multierr" +) + +var ( + // NOTE: These are further restrictions upon the validation that already happens by std.MemPackage.Validate(). + // sub.domain.com/a/any + // sub.domain.com/b/single + // sub.domain.com/c/letter + // sub.domain.com/d/works + // sub.domain.com/r/realm + // sub.domain.com/r/realm/path + // sub.domain.com/p/package/path + // See also tm2/pkg/std/memfile.go. + // XXX test exhaustively balanced futureproof vs restrictive. + reGnoPkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:[a-z])(?:\/_?[a-z][a-z0-9_]*)+$`) + reGnoPkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) +) + +var ( + allowedMemPackageFiles = []string{ + "LICENSE", + "README.md", + "gno.mod", + } + allowedMemPackageFileExtensions = []string{ + ".gno", + } + badMemPackageFileExtensions = []string{ + ".gen.go", + } +) + +type MemPackageType string + +const ( + MemPackageTypeAny MemPackageType = "MemPackageTypeAny" // anything but not filetests only + MemPackageTypeStdlib MemPackageType = "MemPackageTypeStdlib" // stdlibs only + MemPackageTypeNormal MemPackageType = "MemPackageTypeNormal" // no stdlibs, gno pkg path, may include filetests + MemPackageTypeFiletests MemPackageType = "MemPackageTypeFiletests" // filetests only +) + +type ValidateMemPackageOptions struct { + Type MemPackageType +} + +// Validates a non-stdlib mempackage. +func ValidateMemPackage(mpkg *std.MemPackage) error { + return ValidateMemPackageWithOptions(mpkg, ValidateMemPackageOptions{ + Type: MemPackageTypeNormal, // Keep this for defensiveness. + }) +} + +func ValidateMemPackageWithOptions(mpkg *std.MemPackage, opts ValidateMemPackageOptions) (errs error) { + // Check for file sorting, string lengths, uniqueness... + err := mpkg.ValidateBasic() + if err != nil { + return err + } + // Validate mpkg path. + if true && // none of these match... + !reGnoPkgPathURL.MatchString(mpkg.Path) && + !reGnoPkgPathStd.MatchString(mpkg.Path) && + opts.Type != MemPackageTypeAny { // .ValidateBasic() ensured rePkgPathRUL + return fmt.Errorf("invalid package/realm path %q", mpkg.Path) + } + // Check stdlib. + isStdlib := IsStdlib(mpkg.Path) + if isStdlib && !(opts.Type == MemPackageTypeStdlib || opts.Type == MemPackageTypeAny) { + return fmt.Errorf("invalid package path %q: unexpected stdlib-type path", mpkg.Path) + } + if !isStdlib && opts.Type == MemPackageTypeStdlib { + return fmt.Errorf("invalid package path %q: expected stdlib-type path", mpkg.Path) + } + allowedMemPackageFileExtensions := allowedMemPackageFileExtensions + if isStdlib { // Allow transpilation to work on stdlib with native functions. + allowedMemPackageFileExtensions = append(allowedMemPackageFileExtensions, ".go") + } + // Validate package name. + if err := validatePkgName(Name(mpkg.Name)); err != nil { + return err + } + // Validate files. + if mpkg.IsEmpty() { + return fmt.Errorf("package has no files") + } + numGnoFiles := 0 + pkgNameFound := false + for _, mfile := range mpkg.Files { + // Validate file name. + fname := mfile.Name + if endsWithAny(fname, badMemPackageFileExtensions) { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: illegal file extension", fname)) + continue + } + if strings.HasPrefix(fname, ".") { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: file name cannot start with a dot", fname)) + continue + } + if strings.Contains(fname, "/") { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: file name cannot contain a slash", fname)) + continue + } + if !endsWithAny(fname, allowedMemPackageFileExtensions) { + if !slices.Contains(allowedMemPackageFiles, fname) { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: unrecognized file type", fname)) + continue + } + } + // Validate .gno package names. + if strings.HasSuffix(fname, ".gno") { + numGnoFiles += 1 + pkgName, err := PackageNameFromFileBody(path.Join(mpkg.Path, fname), mfile.Body) + if err != nil { + errs = multierr.Append(errs, err) + continue + } + if pkgName != Name(mpkg.Name) { // Check validity but skip if mpkg.Name (already checked). + if err := validatePkgName(pkgName); err != nil { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: invalid package name", pkgName)) + continue + } + } + if opts.Type == MemPackageTypeFiletests || strings.HasSuffix(fname, "_filetest.gno") { + // Any valid package name is OK for filetests. + if pkgName == Name(mpkg.Name) { + pkgNameFound = true + } + } else if strings.HasSuffix(fname, "_test.gno") { + if pkgName == Name(mpkg.Name) || pkgName == Name(mpkg.Name)+"_test" { + pkgNameFound = true + } else { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: invalid package name", pkgName)) + continue + } + } else { + if pkgName == Name(mpkg.Name) { + pkgNameFound = true + } else if opts.Type != MemPackageTypeFiletests { + errs = multierr.Append(errs, fmt.Errorf("invalid file %q: invalid package name", pkgName)) + continue + } + } + } + } + if numGnoFiles == 0 { + errs = multierr.Append(errs, fmt.Errorf("package has no .gno files")) + } + if (opts.Type != MemPackageTypeFiletests) && !pkgNameFound { + errs = multierr.Append(errs, fmt.Errorf("package name %q not found in files", mpkg.Name)) + } + return errs +} diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 1c5a3d186d1..8fb33ac36ef 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -441,7 +441,7 @@ func (x *CallExpr) isCrossing() bool { func (x *CallExpr) SetWithCross() { if !x.isWithCross() { - panic("expected cross(fn)(...)") + panic("expected fn(cur,...)") } x.WithCross = true } @@ -1185,10 +1185,10 @@ func MustPackageNameFromFileBody(name, body string) Name { return pkgName } -// ReadMemPackage initializes a new MemPackage by reading the OS directory -// at dir, and saving it with the given pkgPath (import path). -// The resulting MemPackage will contain the names and content of all *.gno files, -// and additionally README.md, LICENSE. +// ReadMemPackage initializes a new MemPackage by reading the OS directory at +// dir, and saving it with the given pkgPath (import path). The resulting +// MemPackage will contain the names and content of all *.gno files, and +// additionally README.md, LICENSE. // // ReadMemPackage does not perform validation aside from the package's name; // the files are not parsed but their contents are merely stored inside a MemFile. @@ -1200,31 +1200,23 @@ func ReadMemPackage(dir string, pkgPath string) (*std.MemPackage, error) { if err != nil { return nil, err } - allowedFiles := []string{ // make case insensitive? - "LICENSE", - "README.md", - "gno.mod", - } - allowedFileExtensions := []string{ - ".gno", - } - // exceptions to allowedFileExtensions - var rejectedFileExtensions []string + // exceptions to allowedMemPackageFileExtensions + var badFileExtensions []string if IsStdlib(pkgPath) { // Allows transpilation to work on stdlibs with native fns. - allowedFileExtensions = append(allowedFileExtensions, ".go") - rejectedFileExtensions = []string{".gen.go"} + allowedMemPackageFileExtensions = append(allowedMemPackageFileExtensions, ".go") + badFileExtensions = []string{".gen.go"} } list := make([]string, 0, len(files)) for _, file := range files { // Ignore directories and hidden files, only include allowed files & extensions, - // then exclude files that are of the rejected extensions. + // then exclude files that are of the bad extensions. if file.IsDir() || strings.HasPrefix(file.Name(), ".") || - (!endsWithAny(file.Name(), allowedFileExtensions) && !slices.Contains(allowedFiles, file.Name())) || - endsWithAny(file.Name(), rejectedFileExtensions) { + (!endsWithAny(file.Name(), allowedMemPackageFileExtensions) && !slices.Contains(allowedMemPackageFiles, file.Name())) || + endsWithAny(file.Name(), badFileExtensions) { continue } list = append(list, filepath.Join(dir, file.Name())) @@ -1247,54 +1239,66 @@ func MustReadMemPackage(dir string, pkgPath string) *std.MemPackage { return pkg } -// ReadMemPackageFromList creates a new [std.MemPackage] with the specified pkgPath, -// containing the contents of all the files provided in the list slice. -// No parsing or validation is done on the filenames. +// ReadMemPackageFromList creates a new [std.MemPackage] with the specified +// pkgPath, containing the contents of all the files provided in the list +// slice. No parsing is done on the file bodies except package names for +// validation. The returned mempackage must be validated separately with +// gno.ValidateMemPackage(). // -// NOTE: errors out if package name is invalid (characters must be alphanumeric or _, -// lowercase, and must start with a letter, and be the same for normal files -// and normal *_test.gno files, and xxx_test for integration tests). Filetest -// package names are not checked. If the only file present is a single filetest, -// its package name is used. +// Returns both read mempackage and (multi)error if package name is invalid +// (characters must be alphanumeric or _, lowercase, and must start with a +// letter, and be the same for normal files and normal *_test.gno files, and +// xxx_test for integration tests). Filetest package names are not checked. If +// the only file present is a single filetest, its package name is used. // -// XXX TODO pkgPath should instead be derived by inspecting the contents, among them -// the gno.mod file. +// XXX TODO pkgPath should instead be derived by inspecting the contents, among +// them the gno.mod file. func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, error) { mpkg := &std.MemPackage{Path: pkgPath} - var pkgName Name // normal file pkg name - var pkgNameFT Name // filetest pkg name - var pkgNameFTDifferent bool // if pkgNameFT are different + var pkgName Name // normal file pkg name + var pkgNameDiffers bool // normal file pkg name is inconsistent + var pkgNameFT Name // filetest pkg name + var pkgNameFTDiffers bool // filetest pkg name is inconsistent + var errs error // all errors minus filetest pkg name errors. for _, fpath := range list { fname := filepath.Base(fpath) bz, err := os.ReadFile(fpath) if err != nil { return nil, err } - // XXX: should check that all pkg names are the same (else package is invalid) + // Check that all pkg names are the same (else package is invalid). + // Try to derive the package name, but this is not a replacement + // for gno.ValidateMemPackage(). if strings.HasSuffix(fname, ".gno") { var pkgName2 Name pkgName2, err = PackageNameFromFileBody(path.Join(pkgPath, fname), string(bz)) if err != nil { - return nil, err + errs = multierr.Append(errs, err) + continue } if strings.HasSuffix(fname, "_filetest.gno") { // Filetests may have arbitrary package names. - // pkgName2 (of this file) may be unrelated to pkgName of the mem package. - if pkgNameFT == "" && !pkgNameFTDifferent { + // pkgName2 (of this file) may be unrelated to + // pkgName of the mem package. + if pkgNameFT == "" && !pkgNameFTDiffers { pkgNameFT = pkgName2 } else if pkgNameFT != pkgName2 { pkgNameFT = "" - pkgNameFTDifferent = true + pkgNameFTDiffers = true } } else { - // Ensure that package names are the same. if strings.HasSuffix(string(pkgName2), "_test") { pkgName2 = pkgName2[:len(pkgName2)-len("_test")] } - if pkgName == "" { + if pkgName == "" && !pkgNameDiffers { pkgName = pkgName2 } else if pkgName != pkgName2 { - return nil, fmt.Errorf("expected package name %q but got %q", pkgName, pkgName2) + // This happens when transpiling + // tests/files; both mpkg and errors + // will be returned. + pkgName = "" + pkgNameDiffers = true + errs = multierr.Append(errs, fmt.Errorf("%s:0: expected package name %q but got %q", fpath, pkgName, pkgName2)) } } } @@ -1305,27 +1309,33 @@ func ReadMemPackageFromList(list []string, pkgPath string) (*std.MemPackage, err }) } - // If the only file present is a single filetest, its package name is used. - if pkgName == "" && !pkgNameFTDifferent { + // If there were any errors so far, return error. + if errs != nil { + return mpkg, errs + } + // If mpkg is empty, return an error + if mpkg.IsEmpty() { + return mpkg, fmt.Errorf("package has no files") + } + // If pkgNameDiffers, return mpkg and the errors. + if pkgNameDiffers { + return mpkg, errs + } + // If only filetests with the same name, its package name is used. + if pkgName == "" && !pkgNameDiffers && !pkgNameFTDiffers { pkgName = pkgNameFT } - // Still no pkgName... use a sensible default. + // Still no pkgName or invalid; ensure error. if pkgName == "" { - pkgName = "main" + pkgName = "xxxinvalidpackagenamexxx" // sensible default + errs = multierr.Append(errs, fmt.Errorf("package name could be determined")) + } else if err := validatePkgName(pkgName); err != nil { + errs = multierr.Append(errs, err) + return mpkg, errs } mpkg.Name = string(pkgName) - - // If no .gno files are present, package simply does not exist. - if !mpkg.IsEmpty() { - if err := validatePkgName(string(pkgName)); err != nil { - return nil, err - } - } - - // Sort the files for validation purposes. - mpkg.Sort() - + mpkg.Sort() // sort files for gno.ValidateMemPackage(). return mpkg, nil } @@ -2341,9 +2351,9 @@ var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`) // TODO: consider length restrictions. // If this function is changed, ReadMemPackage's documentation should be updated accordingly. -func validatePkgName(name string) error { - if !rePkgName.MatchString(name) { - return fmt.Errorf("cannot create package with invalid name %q", name) +func validatePkgName(name Name) error { + if !rePkgName.MatchString(string(name)) { + return fmt.Errorf("invalid package name %q", name) } return nil } diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index dd50f46753d..bcdc122e7d9 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -60,7 +60,7 @@ type Store interface { // Upon restart, all packages will be re-preprocessed; This // loads BlockNodes and Types onto the store for persistence // version 1. - AddMemPackage(mpkg *std.MemPackage) + AddMemPackage(mpkg *std.MemPackage, mtype MemPackageType) GetMemPackage(path string) *std.MemPackage GetMemFile(path string, name string) *std.MemFile IterMemPackage() <-chan *std.MemPackage @@ -785,7 +785,7 @@ func (ds *defaultStore) incGetPackageIndexCounter() uint64 { } } -func (ds *defaultStore) AddMemPackage(mpkg *std.MemPackage) { +func (ds *defaultStore) AddMemPackage(mpkg *std.MemPackage, mtype MemPackageType) { if bm.OpsEnabled { bm.PauseOpCode() defer bm.ResumeOpCode() @@ -798,7 +798,8 @@ func (ds *defaultStore) AddMemPackage(mpkg *std.MemPackage) { bm.StopStore(size) }() } - err := ValidateMemPackage(mpkg) // NOTE: duplicate validation. + err := ValidateMemPackageWithOptions(mpkg, + ValidateMemPackageOptions{Type: mtype}) if err != nil { panic(fmt.Errorf("invalid mempackage: %w", err)) } diff --git a/gnovm/pkg/gnolang/store_test.go b/gnovm/pkg/gnolang/store_test.go index 664beb5e458..1f060375f18 100644 --- a/gnovm/pkg/gnolang/store_test.go +++ b/gnovm/pkg/gnolang/store_test.go @@ -79,7 +79,7 @@ func TestCopyFromCachedStore(t *testing.T) { Files: []*std.MemFile{ {Name: "math.gno", Body: "package math"}, }, - }) + }, MemPackageTypeAny) // Create dest store and copy. d1, d2 := memdb.NewMemDB(), memdb.NewMemDB() diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 42f128def50..0b62790bbf6 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -35,6 +35,8 @@ const ( ParseModeIntegration // all files even including *_filetest.gno; for linting and testing. ParseModeAll + // a directory of file tests. consider all to be filetests. + ParseModeOnlyFiletests ) // ======================================== @@ -78,7 +80,7 @@ func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( if strings.HasSuffix(file.Name, "_filetest.gno") { continue } - case ParseModeAll: + case ParseModeAll, ParseModeOnlyFiletests: // include all default: panic("should not happen") @@ -98,7 +100,8 @@ func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( } deleteOldIdents(delFunc, gof) // The *ast.File passed all filters. - if strings.HasSuffix(file.Name, "_filetest.gno") { + if strings.HasSuffix(file.Name, "_filetest.gno") || + pmode == ParseModeOnlyFiletests { tgofs = append(tgofs, gof) } else if strings.HasSuffix(file.Name, "_test.gno") && strings.HasSuffix(gof.Name.String(), "_test") { diff --git a/gnovm/pkg/gnolang/validate_mempackage.go b/gnovm/pkg/gnolang/validate_mempackage.go deleted file mode 100644 index b01119ebbd9..00000000000 --- a/gnovm/pkg/gnolang/validate_mempackage.go +++ /dev/null @@ -1,38 +0,0 @@ -package gnolang - -import ( - "regexp" - - "github.com/gnolang/gno/tm2/pkg/std" -) - -var ( - // NOTE: These are further restrictions upon the validation that already happens by std.MemPackage.Validate(). - // sub.domain.com/a/any - // sub.domain.com/b/single - // sub.domain.com/c/letter - // sub.domain.com/d/works - // sub.domain.com/r/realm - // sub.domain.com/r/realm/path - // sub.domain.com/p/package/path - // See also tm2/pkg/std/memfile.go. - // XXX test exhaustively balanced futureproof vs restrictive. - reGnoPkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}\/(?:[a-z])(?:\/_?[a-z][a-z0-9_]*)+$`) - reGnoPkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) -) - -func ValidateMemPackage(mpkg *std.MemPackage) error { - err := mpkg.ValidateBasic() - if err != nil { - return err - } - /* - XXX Uncomment this once all tests pass. - if true && // none of these match... - !reGnoPkgPathURL.MatchString(mpkg.Path) && - !reGnoPkgPathStd.MatchString(mpkg.Path) { - return fmt.Errorf("invalid package/realm path %q", mpkg.Path) - } - */ - return nil -} diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index af178cff975..512e34a8c71 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -277,7 +277,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content // Use last element after / (works also if slash is missing). if !gno.IsRealmPath(pkgPath) { // Type check. - memPkg := &std.MemPackage{ + mpkg := &std.MemPackage{ Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ @@ -286,7 +286,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content }, } // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } @@ -310,7 +310,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content fname = strings.ReplaceAll(fname, "_filetest", "") // save package using realm crawl procedure. - memPkg := &std.MemPackage{ + mpkg := &std.MemPackage{ Name: string(pkgName), Path: pkgPath, Files: []*std.MemFile{ @@ -322,12 +322,12 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content m.Store = tx // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(memPkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } // Run decls and init functions. - m.RunMemPackage(memPkg, true) + m.RunMemPackage(mpkg, true) // Clear store cache and reconstruct machine from committed info // (mimicking on-chain behaviour). tx.Write() diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index f77319ad04b..793970ab766 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -97,7 +97,7 @@ func StoreWithOptions( panic(fmt.Errorf("test store preparing AST: %w", errs)) } } - m.Store.AddMemPackage(mpkg) + m.Store.AddMemPackage(mpkg, gno.MemPackageTypeAny) return m.PreprocessFiles( mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), @@ -213,7 +213,7 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer, prep ReviveEnabled: true, }) if preprocessOnly { - m2.Store.AddMemPackage(mpkg) + m2.Store.AddMemPackage(mpkg, gno.MemPackageTypeStdlib) return m2.PreprocessFiles(mpkg.Name, mpkg.Path, gno.ParseMemPackage(mpkg), true, true, "") } // TODO: make this work when using gno lint. diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 6ad3a105442..474ecc04b17 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -17,7 +17,8 @@ const pkgNameLimit = 256 const pkgPathLimit = 256 var ( - // See also gnovm/pkg/gnolang/validate_mempackage.go. + // See also gnovm/pkg/gnolang/mempackage.go. + // NOTE: DO NOT MODIFY without a pre/post ADR and discussions with core GnoVM and gno.land teams. reFileName = regexp.MustCompile(`^(([a-z0-9_\-]+|[A-Z0-9_\-]+)\.[a-z0-9_]{1,7}|LICENSE|README)$`) rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) rePkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}(\/[a-z0-9\-_]+)+$`) @@ -45,6 +46,9 @@ type MemFile struct { } func (mfile *MemFile) ValidateBasic() error { + if len(mfile.Name) == 0 { + return fmt.Errorf("name cannot be empty") + } if len(mfile.Name) > fileNameLimit { return fmt.Errorf("name length %d exceeds limit %d", len(mfile.Name), fileNameLimit) } @@ -68,8 +72,8 @@ func (mfile *MemFile) Print() error { // stored in memory. It will generally be initialized by package gnolang's // ReadMemPackage. // -// NOTE: in the future, a MemPackage may represent -// updates/additional-files for an existing package. +// NOTE: in the future, a MemPackage may represent updates/additional-files for +// an existing package. type MemPackage struct { Name string `json:"name" yaml:"name"` // package name as declared by `package` Path string `json:"path" yaml:"path"` // import path @@ -108,7 +112,7 @@ func (mpkg *MemPackage) ValidateBasic() error { ) if !sorted { for i := 0; i < len(mpkg.Files); i++ { - fmt.Println(">>>", i, mpkg.Files[i].Name) + fmt.Println("memfile", i, ":", mpkg.Files[i].Name) } return fmt.Errorf("mempackage %q has unsorted files", mpkg.Path) } @@ -186,10 +190,25 @@ func (mpkg *MemPackage) SetFile(name string, body string) *MemFile { return mpkg.NewFile(name, body) } -// Returns true if zero. -// XXX Reconsider renaming all IsEmpty() to IsZero(), each carefully. +// Removes an existing file and returns it or nil. +func (mpkg *MemPackage) DeleteFile(name string) *MemFile { + for i, mfile := range mpkg.Files { + if mfile.Name == name { + mpkg.Files = append(mpkg.Files[:i], mpkg.Files[i+1:]...) + return mfile + } + } + return nil +} + +// Returns true if it has no files. func (mpkg *MemPackage) IsEmpty() bool { - return mpkg.Name == "" || len(mpkg.Files) == 0 + return len(mpkg.Files) == 0 +} + +// Returns true if zero. +func (mpkg *MemPackage) IsZero() bool { + return mpkg.Name == "" && len(mpkg.Files) == 0 } // Write all files into dir. From d9ee35a92559211e1cc90c58a975d78ebdf76be4 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Thu, 22 May 2025 14:06:49 +0200 Subject: [PATCH 75/83] fix(gnodev): validate mpkg function --- contribs/gnodev/pkg/packages/package.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/contribs/gnodev/pkg/packages/package.go b/contribs/gnodev/pkg/packages/package.go index bc005534128..c66870d84a0 100644 --- a/contribs/gnodev/pkg/packages/package.go +++ b/contribs/gnodev/pkg/packages/package.go @@ -36,7 +36,7 @@ func ReadPackageFromDir(fset *token.FileSet, path, dir string) (*Package, error) // here avoid to potentially parse broken files return nil, ErrResolverPackageSkip } - case errors.As(err, &os.ErrNotExist): + case errors.Is(err, os.ErrNotExist), errors.Is(err, gnomod.ErrGnoModNotFound): // gno.mod is not present, continue anyway default: return nil, err @@ -63,7 +63,7 @@ func ReadPackageFromDir(fset *token.FileSet, path, dir string) (*Package, error) } func validateMemPackage(fset *token.FileSet, mempkg *std.MemPackage) error { - if mempkg.IsEmpty() { + if isMemPackageEmpty(mempkg) { return fmt.Errorf("empty package: %w", ErrResolverPackageSkip) } @@ -86,3 +86,17 @@ func validateMemPackage(fset *token.FileSet, mempkg *std.MemPackage) error { return nil } + +func isMemPackageEmpty(mempkg *std.MemPackage) bool { + if mempkg.IsEmpty() { + return true + } + + for _, file := range mempkg.Files { + if isGnoFile(file.Name) || file.Name == "gno.mod" { + return false + } + } + + return true +} From 82efcb38987c1567fdcf2bec9ad897e2fab757be Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Wed, 21 May 2025 16:16:41 +0200 Subject: [PATCH 76/83] fix: add ParseMode argument to `TypeCheckMemPackage` --- gno.land/pkg/sdk/vm/keeper.go | 4 ++-- gnovm/cmd/gno/tool_lint.go | 2 +- gnovm/pkg/gnolang/gotypecheck.go | 5 ++--- gnovm/pkg/gnolang/gotypecheck_test.go | 4 ++-- gnovm/pkg/test/filetest.go | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 9c9c8c95552..0e73f61a27e 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -360,7 +360,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { } // Validate Gno syntax and type check. - _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore) + _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) if err != nil { return ErrTypeCheck(err) } @@ -590,7 +590,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { } // Validate Gno syntax and type check. - _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore) + _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) if err != nil { return "", ErrTypeCheck(err) } diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 93a73b208a6..d2369699241 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -281,7 +281,7 @@ func lintTypeCheck( // gno.TypeCheckMemPackage(mpkg, testStore) var tcErrs error - gopkg, gofset, gofs, _gofs, tgofs, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore) + gopkg, gofset, gofs, _gofs, tgofs, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore, gno.ParseModeAll) // Print errors, and return the first unexpected error. errors := multierr.Errors(tcErrs) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index 32957ba8b4c..ad082e4bcf7 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -45,7 +45,7 @@ type MemPackageGetter interface { // mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. -func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( +func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, pmode ParseMode) ( pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, ) { var gimp *gnoImporter @@ -62,8 +62,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter) ( } gimp.cfg.Importer = gimp - pmode := ParseModeAll // type check all .gno files - strict := true // check gno.mod exists + strict := true // check gno.mod exists pkg, gofset, gofs, _gofs, tgofs, errs = gimp.typeCheckMemPackage(mpkg, pmode, strict) return } diff --git a/gnovm/pkg/gnolang/gotypecheck_test.go b/gnovm/pkg/gnolang/gotypecheck_test.go index 8bb382f6931..80084615ba0 100644 --- a/gnovm/pkg/gnolang/gotypecheck_test.go +++ b/gnovm/pkg/gnolang/gotypecheck_test.go @@ -363,7 +363,7 @@ func TestTypeCheckMemPackage(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - _, _, _, _, _, err := TypeCheckMemPackage(tc.pkg, tc.getter) + _, _, _, _, _, err := TypeCheckMemPackage(tc.pkg, tc.getter, ParseModeIntegration) if tc.check == nil { assert.NoError(t, err) } else { @@ -397,7 +397,7 @@ func TestTypeCheckMemPackage_format(t *testing.T) { } mpkgGetter := mockPackageGetter{} - _, _, _, _, _, err := TypeCheckMemPackage(pkg, mpkgGetter) + _, _, _, _, _, err := TypeCheckMemPackage(pkg, mpkgGetter, ParseModeIntegration) assert.NoError(t, err) assert.Equal(t, input, pkg.Files[0].Body) // unchanged diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index 512e34a8c71..221fbbc63d1 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -286,7 +286,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content }, } // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } @@ -322,7 +322,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content m.Store = tx // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store); err != nil { + if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } From 51635be67ddc80a3df252fe0a6bcb8197490f37b Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 22 May 2025 22:26:45 -0700 Subject: [PATCH 77/83] fix gno lint xxx_test --- gnovm/cmd/gno/tool_lint.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index d2369699241..94f4500e444 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -208,7 +208,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { gs := ts.BeginTransaction(cw, cw, nil) tm.Store = gs pn, _ := tm.PreprocessFiles( - mpkg.Name, mpkg.Path, _tests, false, false, "") + mpkg.Name+"_test", mpkg.Path+"_test", _tests, false, false, "") ppkg.AddUnderscoreTests(pn, _tests) } { From c604710813ac47036ce07227c91dd6ce508d2b1e Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Fri, 23 May 2025 11:00:04 +0200 Subject: [PATCH 78/83] chore: lint --- examples/no_cycles_test.go | 3 ++- gnovm/cmd/gno/tool_fix.go | 5 ++--- gnovm/cmd/gno/tool_lint.go | 2 +- gnovm/pkg/gnolang/gotypecheck.go | 3 ++- gnovm/pkg/gnolang/transpile_gno0p9.go | 2 +- tm2/pkg/std/memfile_test.go | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/no_cycles_test.go b/examples/no_cycles_test.go index 416e77fe069..aa52f2bfbd1 100644 --- a/examples/no_cycles_test.go +++ b/examples/no_cycles_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/packages" "github.com/gnolang/gno/tm2/pkg/std" @@ -28,7 +29,7 @@ func TestNoCycles(t *testing.T) { require.NoError(t, err) // find examples - examples, err := gnomod.ListPkgs(filepath.Join(gnoRoot, "examples")) + examples, err := gnolang.ReadPkgListFromDir(filepath.Join(gnoRoot, "examples")) require.NoError(t, err) for _, example := range examples { if example.Draft { diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index 091ed76284a..528c8ce6770 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -235,7 +235,7 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { gs := ts.BeginTransaction(cw, cw, nil) // These are Go types. - var ppkg = processedPackage{mpkg: mpkg, dir: dir} + ppkg := processedPackage{mpkg: mpkg, dir: dir} var gofset *token.FileSet var gofs, _gofs, tgofs []*ast.File var errs error @@ -250,8 +250,7 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - _, gofset, gofs, _gofs, tgofs, errs = - lintTypeCheck(cio, dir, mpkg, gs) // , false) + _, gofset, gofs, _gofs, tgofs, errs = lintTypeCheck(cio, dir, mpkg, gs) // , false) if errs != nil { // cio.ErrPrintln(errs) already printed. hasError = true diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 94f4500e444..0df974f5bb6 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -162,7 +162,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { gs := ts.BeginTransaction(cw, cw, nil) // These are Go types. - var ppkg = processedPackage{mpkg: mpkg, dir: dir} + ppkg := processedPackage{mpkg: mpkg, dir: dir} var errs error // Run type checking diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index ad082e4bcf7..c95281b9c85 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -31,7 +31,8 @@ func crossing() { } // shim func cross[F any](fn F) F { return fn } // shim func revive[F any](fn F) any { return nil } // shim type realm interface{} // shim -`, pkgName)} +`, pkgName), + } return file } diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index 0b62790bbf6..f91e45c7f86 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -361,7 +361,7 @@ func TranspileGno0p9(mpkg *std.MemPackage, dir string, pn *PackageNode, fnames [ } // Go parse and collect files from mpkg. - var gofset = token.NewFileSet() + gofset := token.NewFileSet() var errs error var xall int = 0 // number translated from part 1 for _, fname := range fnames { diff --git a/tm2/pkg/std/memfile_test.go b/tm2/pkg/std/memfile_test.go index 71b0dad8423..c2e73dd9b0f 100644 --- a/tm2/pkg/std/memfile_test.go +++ b/tm2/pkg/std/memfile_test.go @@ -261,7 +261,7 @@ func TestMemPackage_Validate(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - err := tc.mpkg.Validate() + err := tc.mpkg.ValidateBasic() if tc.errContains != "" { assert.ErrorContains(t, err, tc.errContains) } else { From 3ca93f7ed17ab2e1ecdff0ce5626a3288868cdb6 Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Fri, 23 May 2025 11:00:48 +0200 Subject: [PATCH 79/83] chore: lint pt2 --- .github/golangci.yml | 2 +- gno.land/pkg/sdk/vm/keeper.go | 4 ++-- gnovm/cmd/gno/test.go | 3 +-- gnovm/cmd/gno/tool_fix.go | 24 ++++++++----------- gnovm/cmd/gno/tool_lint.go | 9 +++---- gnovm/pkg/gnolang/gotypecheck.go | 31 ++++++++++++++++++------- gnovm/pkg/gnolang/gotypecheck_test.go | 6 ++--- gnovm/pkg/gnolang/nodes.go | 4 ++-- gnovm/pkg/gnolang/preprocess.go | 14 ++++++----- gnovm/pkg/gnolang/transpile_gno0p9.go | 1 - gnovm/pkg/test/filetest.go | 4 ++-- tm2/pkg/colors/cmd/modcolor/modcolor.go | 10 ++++---- tm2/pkg/std/memfile.go | 12 ++++++---- 13 files changed, 67 insertions(+), 57 deletions(-) diff --git a/.github/golangci.yml b/.github/golangci.yml index 140e4dffc12..8eb52dbbf22 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -90,4 +90,4 @@ issues: linters: - errorlint # Disabled linting of error comparisons, because of lacking std lib support - path: gnovm/pkg/gnolang - text: "string `(cross|.no realm.|crossing)` has (\\d+) occurrences, make it a constant" + text: "string `(realm|cross|.no realm.|crossing)` has (\\d+) occurrences, make it a constant" diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 0e73f61a27e..683d4ae526d 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -360,7 +360,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { } // Validate Gno syntax and type check. - _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) + _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) if err != nil { return ErrTypeCheck(err) } @@ -590,7 +590,7 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { } // Validate Gno syntax and type check. - _, _, _, _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) + _, _, err = gno.TypeCheckMemPackage(memPkg, gnostore, gno.ParseModeProduction) if err != nil { return "", ErrTypeCheck(err) } diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 8f44109b08a..970cbf2c5c4 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -245,8 +245,7 @@ func execTest(cmd *testCmd, args []string, io commands.IO) error { startedAt := time.Now() didPanic = catchPanic(pkg.Dir, pkgPath, io.Err(), func() { if modfile == nil || !modfile.Draft { - _, _, _, _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore) - if errs != nil { + if _, _, errs := lintTypeCheck(io, pkg.Dir, mpkg, opts.TestStore); errs != nil { didError = true // already printed in lintTypeCheck. // io.ErrPrintln(errs) diff --git a/gnovm/cmd/gno/tool_fix.go b/gnovm/cmd/gno/tool_fix.go index 528c8ce6770..5affa569d33 100644 --- a/gnovm/cmd/gno/tool_fix.go +++ b/gnovm/cmd/gno/tool_fix.go @@ -6,13 +6,12 @@ import ( "errors" "flag" "fmt" - "go/ast" - "go/token" goio "io" "io/fs" "os" "path" "path/filepath" + "slices" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -128,12 +127,12 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { cmd.rootDir = gnoenv.RootDir() } - var dirs []string = nil - var hasError bool = false - var err error = nil + var dirs []string + var hasError bool + var err error if cmd.filetestsOnly { - dirs = append([]string(nil), args...) + dirs = slices.Clone(args) } else { dirs, err = gnoPackagesFromArgsRecursively(args) if err != nil { @@ -236,10 +235,6 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { // These are Go types. ppkg := processedPackage{mpkg: mpkg, dir: dir} - var gofset *token.FileSet - var gofs, _gofs, tgofs []*ast.File - var errs error - // Run type checking // FIX STEP 2: ParseGnoMod() // FIX STEP 3: GoParse*() @@ -250,7 +245,8 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { // ParseGnoMod(mpkg); // GoParseMemPackage(mpkg); // g.cmd.Check(); - _, gofset, gofs, _gofs, tgofs, errs = lintTypeCheck(cio, dir, mpkg, gs) // , false) + + _, tfiles, errs := lintTypeCheck(cio, dir, mpkg, gs) if errs != nil { // cio.ErrPrintln(errs) already printed. hasError = true @@ -263,9 +259,9 @@ func execFix(cmd *fixCmd, args []string, cio commands.IO) error { defer tm.Release() // Prepare Go AST for preprocessing. - allgofs := append(gofs, _gofs...) - allgofs = append(allgofs, tgofs...) - errs = gno.PrepareGno0p9(gofset, allgofs, mpkg) + allgofs := append(tfiles.SourceFiles, tfiles.TestPackageFiles...) + allgofs = append(allgofs, tfiles.TestFiles...) + errs = gno.PrepareGno0p9(tfiles.FileSet, allgofs, mpkg) if errs != nil { cio.ErrPrintln(errs) hasError = true diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 0df974f5bb6..e764c61e35a 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -5,8 +5,6 @@ import ( "errors" "flag" "fmt" - "go/ast" - "go/token" "go/types" goio "io" "io/fs" @@ -176,7 +174,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { // GoParseMemPackage(mpkg); // g.cmd.Check(); if !mod.Draft { - _, _, _, _, _, errs = lintTypeCheck(io, dir, mpkg, gs) + _, _, errs = lintTypeCheck(io, dir, mpkg, gs) if errs != nil { // io.ErrPrintln(errs) printed above. hasError = true @@ -273,15 +271,14 @@ func lintTypeCheck( testStore gno.Store) ( // Results: gopkg *types.Package, - gofset *token.FileSet, - gofs, _gofs, tgofs []*ast.File, + tfiles *gno.TypeCheckFilesResult, lerr error, ) { //---------------------------------------- // gno.TypeCheckMemPackage(mpkg, testStore) var tcErrs error - gopkg, gofset, gofs, _gofs, tgofs, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore, gno.ParseModeAll) + gopkg, tfiles, tcErrs = gno.TypeCheckMemPackage(mpkg, testStore, gno.ParseModeAll) // Print errors, and return the first unexpected error. errors := multierr.Errors(tcErrs) diff --git a/gnovm/pkg/gnolang/gotypecheck.go b/gnovm/pkg/gnolang/gotypecheck.go index c95281b9c85..e08f195e4ca 100644 --- a/gnovm/pkg/gnolang/gotypecheck.go +++ b/gnovm/pkg/gnolang/gotypecheck.go @@ -42,12 +42,19 @@ type MemPackageGetter interface { GetMemPackage(path string) *std.MemPackage } +type TypeCheckFilesResult struct { + FileSet *token.FileSet + SourceFiles []*ast.File // All normal .gno files (and _test.gno files if wtests). + TestPackageFiles []*ast.File // All files in test packages (_test.gno & _testfile.gno). + TestFiles []*ast.File // All standalone test files (_testfile.gno). +} + // TypeCheckMemPackage performs type validation and checking on the given // mpkg. To retrieve dependencies, it uses getter. // // The syntax checking is performed entirely using Go's go/types package. func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, pmode ParseMode) ( - pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, + pkg *types.Package, tfiles *TypeCheckFilesResult, errs error, ) { var gimp *gnoImporter gimp = &gnoImporter{ @@ -64,8 +71,7 @@ func TypeCheckMemPackage(mpkg *std.MemPackage, getter MemPackageGetter, pmode Pa gimp.cfg.Importer = gimp strict := true // check gno.mod exists - pkg, gofset, gofs, _gofs, tgofs, errs = gimp.typeCheckMemPackage(mpkg, pmode, strict) - return + return gimp.typeCheckMemPackage(mpkg, pmode, strict) } type gnoImporterResult struct { @@ -142,7 +148,7 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ pmode = ParseModeIntegration } strict := false // don't check for gno.mod for imports. - pkg, _, _, _, _, errs := gimp.typeCheckMemPackage(mpkg, pmode, strict) + pkg, _, errs := gimp.typeCheckMemPackage(mpkg, pmode, strict) if errs != nil { result.err = errs result.pending = false @@ -163,21 +169,21 @@ func (gimp *gnoImporter) ImportFrom(pkgPath, _ string, _ types.ImportMode) (*typ // ParseModeProduction when type-checking imports. // - strict: If true errors on gno.mod version mismatch. func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMode, strict bool) ( - pkg *types.Package, gofset *token.FileSet, gofs, _gofs, tgofs []*ast.File, errs error, + pkg *types.Package, tfiles *TypeCheckFilesResult, errs error, ) { // See adr/pr4264_lint_transpile.md // STEP 2: Check gno.mod version. if strict { _, err := ParseCheckGnoMod(mpkg) if err != nil { - return nil, nil, nil, nil, nil, err + return nil, nil, err } } // STEP 3: Parse the mem package to Go AST. - gofset, gofs, _gofs, tgofs, errs = GoParseMemPackage(mpkg, pmode) + gofset, gofs, _gofs, tgofs, errs := GoParseMemPackage(mpkg, pmode) if errs != nil { - return nil, nil, nil, nil, nil, errs + return nil, nil, errs } if pmode == ParseModeProduction && (len(_gofs) > 0 || len(tgofs) > 0) { panic("unexpected test files from GoParseMemPackage()") @@ -267,7 +273,14 @@ func (gimp *gnoImporter) typeCheckMemPackage(mpkg *std.MemPackage, pmode ParseMo } */ } - return pkg, gofset, gofs, _gofs, tgofs, multierr.Combine(gimp.errors[numErrs:]...) + + tfiles = &TypeCheckFilesResult{ + FileSet: gofset, + SourceFiles: gofs, + TestPackageFiles: _gofs, + TestFiles: gofs, + } + return pkg, tfiles, multierr.Combine(gimp.errors[numErrs:]...) } func deleteOldIdents(idents map[string]func(), gof *ast.File) { diff --git a/gnovm/pkg/gnolang/gotypecheck_test.go b/gnovm/pkg/gnolang/gotypecheck_test.go index 80084615ba0..9eaca8695ab 100644 --- a/gnovm/pkg/gnolang/gotypecheck_test.go +++ b/gnovm/pkg/gnolang/gotypecheck_test.go @@ -363,7 +363,7 @@ func TestTypeCheckMemPackage(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - _, _, _, _, _, err := TypeCheckMemPackage(tc.pkg, tc.getter, ParseModeIntegration) + _, _, err := TypeCheckMemPackage(tc.pkg, tc.getter, ParseModeIntegration) if tc.check == nil { assert.NoError(t, err) } else { @@ -397,7 +397,7 @@ func TestTypeCheckMemPackage_format(t *testing.T) { } mpkgGetter := mockPackageGetter{} - _, _, _, _, _, err := TypeCheckMemPackage(pkg, mpkgGetter, ParseModeIntegration) + _, _, err := TypeCheckMemPackage(pkg, mpkgGetter, ParseModeIntegration) assert.NoError(t, err) assert.Equal(t, input, pkg.Files[0].Body) // unchanged @@ -409,7 +409,7 @@ func TestTypeCheckMemPackage_format(t *testing.T) { } ` - _, _, _, _, _, _, err = TypeCheckMemPackage(pkg, mpkgGetter) + _, _, err = TypeCheckMemPackage(pkg, mpkgGetter) assert.NoError(t, err) assert.NotEqual(t, input, pkg.Files[0].Body) assert.Equal(t, expected, pkg.Files[0].Body) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 8fb33ac36ef..e2c5b11e9fc 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1157,8 +1157,8 @@ type FileSet struct { Files []*FileNode } -func (fset FileSet) GetFileNames() (fnames []Name) { - for _, fnode := range fset.Files { +func (fs FileSet) GetFileNames() (fnames []Name) { + for _, fnode := range fs.Files { fnames = append(fnames, fnode.Name) } return diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a2531540a39..cef545b6553 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -14,8 +14,10 @@ import ( ) const ( - blankIdentifier = "_" - debugFind = false // toggle when debugging. + debugFind = false // toggle when debugging. + + blankIdentifier = "_" + AttrPreprocessFuncLitExpr = "FuncLitExpr" ) // Predefine (initStaticBlocks) and partially evaluates all names @@ -465,7 +467,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return n, TRANS_CONTINUE } if _, ok := n.(*FuncLitExpr); ok { - if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == AttrPreprocessFuncLitExpr { clearSkip = true // clear what preprocess1 will do. return n, TRANS_SKIP } @@ -507,7 +509,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return n, TRANS_CONTINUE } if _, ok := n.(*FuncLitExpr); ok { - if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == AttrPreprocessFuncLitExpr { return n, TRANS_SKIP } } @@ -726,7 +728,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { case *FuncLitExpr: // retrieve cached function type. ft := evalStaticType(store, last, &n.Type).(*FuncType) - if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == "FuncLitExpr" { + if n.GetAttribute(ATTR_PREPROCESS_SKIPPED) == AttrPreprocessFuncLitExpr { // Machine still needs it. Clear it @ initStaticBlocks. // n.DelAttribute(ATTR_PREPROCESS_SKIPPED) for _, p := range ns { @@ -4045,7 +4047,7 @@ func findUndefinedAny(store Store, last BlockNode, x Expr, stack []Name, definin } _, _, found := findLastFunction(last, nil) if !found { - cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, "FuncLitExpr") + cx.SetAttribute(ATTR_PREPROCESS_SKIPPED, AttrPreprocessFuncLitExpr) } case *FieldTypeExpr: // FIELD return findUndefinedT(store, last, cx.Type, stack, defining, isalias, direct) diff --git a/gnovm/pkg/gnolang/transpile_gno0p9.go b/gnovm/pkg/gnolang/transpile_gno0p9.go index f91e45c7f86..668b59e09c1 100644 --- a/gnovm/pkg/gnolang/transpile_gno0p9.go +++ b/gnovm/pkg/gnolang/transpile_gno0p9.go @@ -84,7 +84,6 @@ func GoParseMemPackage(mpkg *std.MemPackage, pmode ParseMode) ( // include all default: panic("should not happen") - } // Go parse file. const parseOpts = parser.ParseComments | diff --git a/gnovm/pkg/test/filetest.go b/gnovm/pkg/test/filetest.go index 221fbbc63d1..f652f55237d 100644 --- a/gnovm/pkg/test/filetest.go +++ b/gnovm/pkg/test/filetest.go @@ -286,7 +286,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content }, } // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { + if _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } @@ -322,7 +322,7 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, fname string, content m.Store = tx // Validate Gno syntax and type check. - if _, _, _, _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { + if _, _, err := gno.TypeCheckMemPackage(mpkg, m.Store, gno.ParseModeAll); err != nil { tcError = fmt.Sprintf("%v", err.Error()) } diff --git a/tm2/pkg/colors/cmd/modcolor/modcolor.go b/tm2/pkg/colors/cmd/modcolor/modcolor.go index 6b6728b3d2c..aa6d0c6f679 100644 --- a/tm2/pkg/colors/cmd/modcolor/modcolor.go +++ b/tm2/pkg/colors/cmd/modcolor/modcolor.go @@ -10,8 +10,10 @@ import ( "github.com/gnolang/gno/tm2/pkg/colors" ) -var order = []colors.Color{colors.None, colors.Gray, colors.Cyan, colors.Blue, colors.Green, colors.Yellow, colors.Red, colors.Magenta} -var modPtr = flag.Int("mod", 2, "modulo number of lines; maximum 8") +var ( + order = []colors.Color{colors.None, colors.Gray, colors.Cyan, colors.Blue, colors.Green, colors.Yellow, colors.Red, colors.Magenta} + modPtr = flag.Int("mod", 2, "modulo number of lines; maximum 8") +) func main() { flag.Parse() @@ -19,8 +21,8 @@ func main() { panic("--mod must be between 2 and 8") } - var mod = *modPtr - var rin = bufio.NewReader(os.Stdin) + mod := *modPtr + rin := bufio.NewReader(os.Stdin) for i := 0; ; i++ { line, err := rin.ReadString('\n') if err == io.EOF { diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 474ecc04b17..a277a4e0ff3 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -12,9 +12,11 @@ import ( // XXX rename to mempackage.go -const fileNameLimit = 256 -const pkgNameLimit = 256 -const pkgPathLimit = 256 +const ( + fileNameLimit = 256 + pkgNameLimit = 256 + pkgPathLimit = 256 +) var ( // See also gnovm/pkg/gnolang/mempackage.go. @@ -136,7 +138,7 @@ func (mpkg *MemPackage) ValidateBasic() error { // Returns an error if lowercase(file.Name) are not unique. func (mpkg *MemPackage) Uniq() error { - var uniq = make(map[string]struct{}, len(mpkg.Files)) + uniq := make(map[string]struct{}, len(mpkg.Files)) for _, mfile := range mpkg.Files { lname := strings.ToLower(mfile.Name) if _, exists := uniq[lname]; exists { @@ -217,7 +219,7 @@ func (mpkg *MemPackage) WriteTo(dir string) error { for _, mfile := range mpkg.Files { // fmt.Printf(" - %s (%d bytes)\n", mfile.Name, len(mfile.Body)) fpath := filepath.Join(dir, mfile.Name) - err := ioutil.WriteFile(fpath, []byte(mfile.Body), 0644) + err := ioutil.WriteFile(fpath, []byte(mfile.Body), 0o644) if err != nil { return err } From c673fd1e5a13660686a0cac896419b09d7d2e3ab Mon Sep 17 00:00:00 2001 From: gfanton <8671905+gfanton@users.noreply.github.com> Date: Fri, 23 May 2025 18:34:50 +0200 Subject: [PATCH 80/83] fix: integration gas update --- gno.land/pkg/integration/testdata/gc.txtar | 2 +- gno.land/pkg/integration/testdata/gnokey_gasfee.txtar | 4 ++-- gno.land/pkg/integration/testdata/simulate_gas.txtar | 4 ++-- gno.land/pkg/integration/testdata/wugnot.txtar | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gno.land/pkg/integration/testdata/gc.txtar b/gno.land/pkg/integration/testdata/gc.txtar index ffbca5b84be..6dbac65f3c7 100644 --- a/gno.land/pkg/integration/testdata/gc.txtar +++ b/gno.land/pkg/integration/testdata/gc.txtar @@ -6,7 +6,7 @@ loadpkg gno.land/r/gc $WORK/r/gc gnoland start gnokey maketx call -pkgpath gno.land/r/gc -func Alloc -gas-fee 100000ugnot -gas-wanted 3000000 -simulate skip -broadcast -chainid tendermint_test test1 -stdout 'GAS USED: 507741' +stdout 'GAS USED: 508221' -- r/gc/gc.gno -- package gc diff --git a/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar b/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar index 3e4dd517d7f..c55ad7fc17c 100644 --- a/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar +++ b/gno.land/pkg/integration/testdata/gnokey_gasfee.txtar @@ -11,8 +11,8 @@ stdout '"coins": "10000000000000ugnot"' # Tx add package -simulate only, estimate gas used and gas fee gnokey maketx addpkg -pkgdir $WORK/hello -pkgpath gno.land/r/hello -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate only test1 -stdout 'GAS USED: 186176' -stdout 'INFO: estimated gas usage: 186176, gas fee: 196ugnot, current gas price: 1000gas/1ugnot' +stdout 'GAS USED: 186496' +stdout 'INFO: estimated gas usage: 186496, gas fee: 196ugnot, current gas price: 1000gas/1ugnot' ## No fee was charged, and the sequence number did not change. gnokey query auth/accounts/$test1_user_addr diff --git a/gno.land/pkg/integration/testdata/simulate_gas.txtar b/gno.land/pkg/integration/testdata/simulate_gas.txtar index 2119e90424f..16c7c1ff5f3 100644 --- a/gno.land/pkg/integration/testdata/simulate_gas.txtar +++ b/gno.land/pkg/integration/testdata/simulate_gas.txtar @@ -6,11 +6,11 @@ gnoland start # simulate only gnokey maketx call -pkgpath gno.land/r/simulate -func Hello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate only test1 -stdout 'GAS USED: 104694' +stdout 'GAS USED: 105014' # simulate skip gnokey maketx call -pkgpath gno.land/r/simulate -func Hello -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test -simulate skip test1 -stdout 'GAS USED: 104694' # same as simulate only +stdout 'GAS USED: 105014' # same as simulate only -- package/package.gno -- diff --git a/gno.land/pkg/integration/testdata/wugnot.txtar b/gno.land/pkg/integration/testdata/wugnot.txtar index dde03ae3f02..852fb4923d7 100644 --- a/gno.land/pkg/integration/testdata/wugnot.txtar +++ b/gno.land/pkg/integration/testdata/wugnot.txtar @@ -18,14 +18,14 @@ stdout 'Known accounts..: 0' # user1 balance should be empty gnokey query vm/qeval --data "gno.land/r/demo/wugnot.BalanceOf(\"${user1_user_addr}\")" -stdout '0 uint64' +stdout '0 int64' # Deposit using user1 gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Deposit -send 10000ugnot -gas-fee 100000ugnot -gas-wanted 50000000 -broadcast -chainid=tendermint_test user1 stdout 'OK!' gnokey query vm/qeval --data "gno.land/r/demo/wugnot.BalanceOf(\"${user1_user_addr}\")" -stdout '10000 uint64' +stdout '10000 int64' gnokey query vm/qrender --data "gno.land/r/demo/wugnot:" stdout 'Total supply..: 10000' @@ -34,17 +34,17 @@ stdout 'Known accounts..: 1' # user2 balance should be empty gnokey query vm/qeval --data "gno.land/r/demo/wugnot.BalanceOf(\"${user2_user_addr}\")" -stdout '0 uint64' +stdout '0 int64' # Deposit using user2 gnokey maketx call -pkgpath gno.land/r/demo/wugnot -func Deposit -send 10000ugnot -gas-fee 10000ugnot -gas-wanted 10_000_000 -broadcast -chainid=tendermint_test user2 stdout 'OK!' gnokey query vm/qeval --data "gno.land/r/demo/wugnot.BalanceOf(\"${user1_user_addr}\")" -stdout '10000 uint64' +stdout '10000 int64' gnokey query vm/qeval --data "gno.land/r/demo/wugnot.BalanceOf(\"${user2_user_addr}\")" -stdout '10000 uint64' +stdout '10000 int64' ## We should have 2 accounts gnokey query vm/qrender --data "gno.land/r/demo/wugnot:" From 2cc60ed9cc31d378863709c727cc684a4e2bc5dd Mon Sep 17 00:00:00 2001 From: Jae Kwon <53785+jaekwon@users.noreply.github.com> Date: Sat, 24 May 2025 02:09:49 -0700 Subject: [PATCH 81/83] Apply suggestions from code review Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- gnovm/cmd/gno/tool_lint.go | 3 +-- tm2/pkg/std/memfile.go | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index e764c61e35a..e1308e4d96b 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -9,7 +9,6 @@ import ( goio "io" "io/fs" "os" - "path" "path/filepath" "github.com/gnolang/gno/gnovm/pkg/gnoenv" @@ -105,7 +104,7 @@ func execLint(cmd *lintCmd, args []string, io commands.IO) error { } // Read and parse gno.mod directly. - fpath := path.Join(dir, "gno.mod") + fpath := filepath.Join(dir, "gno.mod") mod, err := gnomod.ParseFilepath(fpath) if errors.Is(err, fs.ErrNotExist) { if cmd.autoGnomod { diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index a277a4e0ff3..5ad8160165c 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -28,7 +28,7 @@ var ( ) //---------------------------------------- -// MemPackage +// MemFile // A MemFile is the simplest representation of a "file". // @@ -73,6 +73,7 @@ func (mfile *MemFile) Print() error { // MemPackage represents the information and files of a package which will be // stored in memory. It will generally be initialized by package gnolang's // ReadMemPackage. +// Note: a package does not support subfolders. // // NOTE: in the future, a MemPackage may represent updates/additional-files for // an existing package. @@ -129,9 +130,6 @@ func (mpkg *MemPackage) ValidateBasic() error { if err := mfile.ValidateBasic(); err != nil { return fmt.Errorf("invalid file in package: %w", err) } - if !reFileName.MatchString(mfile.Name) { - return fmt.Errorf("invalid file name %q, failed to match %q", mfile.Name, reFileName) - } } return nil } From 075b2059f13be87d061b3c5fce89dc54ff30b20c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 24 May 2025 02:15:54 -0700 Subject: [PATCH 82/83] let file names have some more dots --- tm2/pkg/std/memfile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index 5ad8160165c..7db6946222c 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -21,7 +21,7 @@ const ( var ( // See also gnovm/pkg/gnolang/mempackage.go. // NOTE: DO NOT MODIFY without a pre/post ADR and discussions with core GnoVM and gno.land teams. - reFileName = regexp.MustCompile(`^(([a-z0-9_\-]+|[A-Z0-9_\-]+)\.[a-z0-9_]{1,7}|LICENSE|README)$`) + reFileName = regexp.MustCompile(`^(([a-z0-9_\-]+|[A-Z0-9_\-]+)(\.[a-z0-9_]+)*\.[a-z0-9_]{1,7}|LICENSE|README)$`) rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) rePkgPathURL = regexp.MustCompile(`^([a-z0-9-]+\.)*[a-z0-9-]+\.[a-z]{2,}(\/[a-z0-9\-_]+)+$`) rePkgPathStd = regexp.MustCompile(`^([a-z][a-z0-9_]*\/)*[a-z][a-z0-9_]+$`) From 40a1c610e0c52abe03684ca269d1e16d5a8d85ec Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 24 May 2025 02:27:22 -0700 Subject: [PATCH 83/83] ... --- gnovm/pkg/gnolang/store_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/store_test.go b/gnovm/pkg/gnolang/store_test.go index 1f2f89311a8..14d6b671c86 100644 --- a/gnovm/pkg/gnolang/store_test.go +++ b/gnovm/pkg/gnolang/store_test.go @@ -144,7 +144,7 @@ func TestFindByPrefix(t *testing.T) { Files: []*std.MemFile{ {Name: lib + ".gno", Body: "package " + lib}, }, - }) + }, MemPackageTypeAny) } // Add pkgs @@ -156,7 +156,7 @@ func TestFindByPrefix(t *testing.T) { Files: []*std.MemFile{ {Name: name + ".gno", Body: "package " + name}, }, - }) + }, MemPackageTypeAny) } for _, tc := range cases {