Skip to content

Commit

Permalink
feat(cmd/gno): allow dirs and arbitrary expressions on gno run (gnola…
Browse files Browse the repository at this point in the history
  • Loading branch information
thehowl committed Jul 23, 2023
1 parent d2c614f commit 4df47de
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 17 deletions.
93 changes: 85 additions & 8 deletions gnovm/cmd/gno/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ package main

import (
"context"
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"strings"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
"github.com/gnolang/gno/gnovm/tests"
Expand All @@ -12,6 +17,7 @@ import (
type runCfg struct {
verbose bool
rootDir string
expr string
}

func newRunCmd(io *commands.IO) *commands.Command {
Expand Down Expand Up @@ -44,6 +50,13 @@ func (c *runCfg) RegisterFlags(fs *flag.FlagSet) {
"",
"clone location of github.com/gnolang/gno (gnodev tries to guess it)",
)

fs.StringVar(
&c.expr,
"expr",
"main()",
"value of expression to evaluate. Defaults to executing function main() with no args",
)
}

func execRun(cfg *runCfg, args []string, io *commands.IO) error {
Expand All @@ -67,23 +80,87 @@ func execRun(cfg *runCfg, args []string, io *commands.IO) error {
testStore.SetLogStoreOps(true)
}

if len(args) == 0 {
args = []string{"."}
}

// read files
files, err := parseFiles(args)
if err != nil {
return err
}

if len(files) == 0 {
return errors.New("no files to run")
}

m := gno.NewMachineWithOptions(gno.MachineOptions{
PkgPath: "main",
PkgPath: string(files[0].PkgName),
Output: stdout,
Store: testStore,
})

defer m.Release()

// read files
files := make([]*gno.FileNode, len(args))
for i, fname := range args {
files[i] = gno.MustReadFile(fname)
}

// run files
m.RunFiles(files...)
m.RunMain()
runExpr(m, cfg.expr)

return nil
}

func parseFiles(fnames []string) ([]*gno.FileNode, error) {
files := make([]*gno.FileNode, 0, len(fnames))
for _, fname := range fnames {
if s, err := os.Stat(fname); err == nil && s.IsDir() {
subFns, err := listNonTestFiles(fname)
if err != nil {
return nil, err
}
subFiles, err := parseFiles(subFns)
if err != nil {
return nil, err
}
files = append(files, subFiles...)
continue
} else if err != nil {
// either not found or some other kind of error --
// in either case not a file we can parse.
return nil, err
}
files = append(files, gno.MustReadFile(fname))
}
return files, nil
}

func listNonTestFiles(dir string) ([]string, error) {
fs, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
fn := make([]string, 0, len(fs))
for _, f := range fs {
n := f.Name()
if isGnoFile(f) &&
!strings.HasSuffix(n, "_test.gno") &&
!strings.HasPrefix(n, "_filetest.gno") {
fn = append(fn, filepath.Join(dir, n))
}
}
return fn, nil
}

func runExpr(m *gno.Machine, expr string) {
defer func() {
if r := recover(); r != nil {
fmt.Printf("panic running expression %s: %v\n%s\n",
expr, r, m.String())
panic(r)
}
}()
ex, err := gno.ParseExpr(expr)
if err != nil {
panic(fmt.Errorf("could not parse: %w", err))
}
m.Eval(ex)
}
53 changes: 45 additions & 8 deletions gnovm/cmd/gno/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,57 @@ func TestRunApp(t *testing.T) {
stdoutShouldContain: "hello world!",
},
{
args: []string{"run", "../../tests/integ/run-main/"},
recoverShouldContain: "read ../../tests/integ/run-main/: is a directory", // FIXME: should work
args: []string{"run", "../../tests/integ/run-main/"},
stdoutShouldContain: "hello world!",
},
{
args: []string{"run", "../../tests/integ/does-not-exist"},
errShouldContain: "no such file or directory",
},
{
args: []string{"run", "../../tests/integ/run-namedpkg/main.gno"},
stdoutShouldContain: "hello, other world!",
},
{
args: []string{"run", "../../tests/integ/run-package"},
recoverShouldContain: "name main not declared",
},
{
args: []string{"run", "-expr", "Hello()", "../../tests/integ/run-package"},
stdoutShouldContain: "called Hello",
},
{
args: []string{"run", "-expr", "World()", "../../tests/integ/run-package"},
stdoutShouldContain: "called World",
},
{
args: []string{"run", "-expr", "otherFile()", "../../tests/integ/run-package"},
stdoutShouldContain: "hello from package2.gno",
},
{
args: []string{
"run", "-expr", "otherFile()",
"../../tests/integ/run-package/package.gno",
},
recoverShouldContain: "name otherFile not declared",
},
{
args: []string{
"run", "-expr", "otherFile()",
"../../tests/integ/run-package/package.gno",
"../../tests/integ/run-package/package2.gno",
},
stdoutShouldContain: "hello from package2.gno",
},
{
args: []string{"run", "../../tests/integ/does-not-exist"},
recoverShouldContain: "open ../../tests/integ/does-not-exist: no such file or directory",
args: []string{"run", "-expr", "WithArg(1)", "../../tests/integ/run-package"},
stdoutShouldContain: "one",
},
{
args: []string{"run", "../../tests/integ/run-namedpkg/main.gno"},
recoverShouldContain: "expected package name [main] but got [namedpkg]", // FIXME: should work
args: []string{"run", "-expr", "WithArg(-255)", "../../tests/integ/run-package"},
stdoutShouldContain: "out of range!",
},
// TODO: multiple files
// TODO: a test file
// TODO: a file without main
// TODO: args
// TODO: nativeLibs VS stdlibs
// TODO: with gas meter
Expand Down
2 changes: 1 addition & 1 deletion gnovm/tests/integ/run-namedpkg/main.gno
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package namedpkg

func main() {
println("hello world!")
println("hello, other world!")
}
26 changes: 26 additions & 0 deletions gnovm/tests/integ/run-package/package.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package pkg

func Hello() {
println("called Hello")
}

func World() {
println("called World")
}

func hello() {
println("called hello")
}

func WithArg(i int) {
switch i {
case 0:
println("zero")
case 1:
println("one")
case 2:
println("two")
default:
println("out of range! :S")
}
}
5 changes: 5 additions & 0 deletions gnovm/tests/integ/run-package/package2.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pkg

func otherFile() {
println("hello from package2.gno!")
}

0 comments on commit 4df47de

Please sign in to comment.