Skip to content

Commit 60a1d92

Browse files
authored
feat(gnovm): Rewrite AST prior go type checking to avoid inter-realm type check errors. (#4156)
1 parent fd67023 commit 60a1d92

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

gnovm/pkg/gnolang/gotypecheck.go

+38
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package gnolang
22

33
import (
44
"bytes"
5+
"errors"
56
"go/ast"
67
"go/format"
78
"go/parser"
@@ -13,6 +14,7 @@ import (
1314

1415
"github.com/gnolang/gno/gnovm"
1516
"go.uber.org/multierr"
17+
"golang.org/x/tools/go/ast/astutil"
1618
)
1719

1820
// type checking (using go/types)
@@ -140,6 +142,11 @@ func (g *gnoImporter) parseCheckMemPackage(mpkg *gnovm.MemPackage, fmt bool) (*t
140142
deleteOldIdents(delFunc, f)
141143
}
142144

145+
if err := filterCrossing(f); err != nil {
146+
errs = multierr.Append(errs, err)
147+
continue
148+
}
149+
143150
// enforce formatting
144151
if fmt {
145152
var buf bytes.Buffer
@@ -179,3 +186,34 @@ func deleteOldIdents(idents map[string]func(), f *ast.File) {
179186
}
180187
}
181188
}
189+
190+
func filterCrossing(f *ast.File) (err error) {
191+
astutil.Apply(f, nil, func(c *astutil.Cursor) bool {
192+
switch n := c.Node().(type) {
193+
case *ast.ExprStmt:
194+
if ce, ok := n.X.(*ast.CallExpr); ok {
195+
if id, ok := ce.Fun.(*ast.Ident); ok && id.Name == "crossing" {
196+
// Validate syntax.
197+
if len(ce.Args) != 0 {
198+
err = errors.New("crossing called with non empty parameters")
199+
}
200+
// Delete statement 'crossing()'.
201+
c.Delete()
202+
}
203+
}
204+
case *ast.CallExpr:
205+
if id, ok := n.Fun.(*ast.Ident); ok && id.Name == "cross" {
206+
// Replace expression 'cross(x)' by 'x'.
207+
var a ast.Node
208+
if len(n.Args) == 1 {
209+
a = n.Args[0]
210+
} else {
211+
err = errors.New("cross called with invalid parameters")
212+
}
213+
c.Replace(a)
214+
}
215+
}
216+
return true
217+
})
218+
return err
219+
}

gnovm/pkg/test/filetest.go

+6
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,12 @@ func (opts *TestOptions) runTest(m *gno.Machine, pkgPath, filename string, conte
262262
}
263263
orig, tx := m.Store, m.Store.BeginTransaction(nil, nil, nil)
264264
m.Store = tx
265+
266+
// Validate Gno syntax and type check.
267+
if err := gno.TypeCheckMemPackageTest(memPkg, m.Store); err != nil {
268+
return runResult{Error: err.Error()}
269+
}
270+
265271
// Run decls and init functions.
266272
m.RunMemPackage(memPkg, true)
267273
// Clear store cache and reconstruct machine from committed info

gnovm/tests/files/extern/timtadh/data_structures/types/string.gno

+4-4
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ func (self ByteSlice) Hash() int {
7070

7171
func hash(s []byte) int {
7272
res := sha256.Sum256(s)
73-
return int(s[0]) |
74-
int(s[1]<<8) |
75-
int(s[2]<<16) |
76-
int(s[3]<<24)
73+
return int(res[0]) |
74+
int(res[1]<<8) |
75+
int(res[2]<<16) |
76+
int(res[3]<<24)
7777
}

0 commit comments

Comments
 (0)