Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(repl): Add support for new declarations. #1044

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions gnovm/pkg/repl/repl.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,17 @@ func (r *Repl) Process(input string) (out string, err error) {
}
}()
r.state.id++
exp, expErr := r.parseExpression(input)
if expErr == nil {
return r.handleExpression(exp)
}

decl, declErr := r.parseDeclaration(input)
if declErr == nil {
return r.handleDeclarations(decl)
}

exp, expErr := r.parseExpression(input)
if expErr == nil {
return r.handleExpression(exp)
}

return "", fmt.Errorf("error parsing code:\n\t- as expression (error: %q)\n\t- as declarations (error: %q)", expErr.Error(), declErr.Error())
}

Expand All @@ -173,7 +174,6 @@ func (r *Repl) handleExpression(e *ast.File) (string, error) {
r.state.machine.RunStatement(gno.S(gno.Call(gno.X(fmt.Sprintf("%s%d", executedFunc, r.state.id)))))

// Read the result from the output buffer after calling main function.

b, err := io.ReadAll(r.rw)
if err != nil {
return "", fmt.Errorf("error reading output buffer: %w", err)
Expand All @@ -187,27 +187,36 @@ func (r *Repl) handleDeclarations(fn *ast.File) (string, error) {
b bytes.Buffer
nonImportsCount int
)

ast.Inspect(fn, func(n ast.Node) bool {
var writeNode bool
var ns string
var (
writeNode bool
ns string
)

switch t := n.(type) {
// TODO:
// token.CONST *ValueSpec
// token.TYPE *TypeSpec
// token.VAR *ValueSpec
case *ast.GenDecl:
if t.Tok != token.IMPORT {
tok := t.Tok

if tok != token.IMPORT &&
tok != token.TYPE &&
tok != token.CONST &&
tok != token.VAR {
break
}

writeNode = true
ns = r.nodeToString(n)

if tok != token.IMPORT {
nonImportsCount++
break
}

i, ok := t.Specs[0].(*ast.ImportSpec)
if !ok {
break
}

ns = r.nodeToString(n)
r.state.imports[i.Path.Value] = ns
case *ast.FuncDecl:
writeNode = true
Expand Down
88 changes: 88 additions & 0 deletions gnovm/pkg/repl/repl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,45 @@ var fixtures = []struct {
},
},
},
{
Name: "Add new constant",
CodeSteps: []step{
{
Line: "const test2, test3 = \"test_string2\", \"test_string3\"",
Result: "const test2, test3 = \"test_string2\", \"test_string3\"\n",
},
{
Line: "const test = \"test_string\"",
Result: "const test = \"test_string\"\n",
},
},
},
{
Name: "Add struct and functions",
CodeSteps: []step{
{
Line: "type MyStruct struct { count int}",
Result: "type MyStruct struct{ count int }\n",
},
{
Line: "func (s *MyStruct) Add(){s.count++}",
Result: "func (s *MyStruct) Add()\t{ s.count++ }\n",
},
},
},
{
Name: "Add new var",
CodeSteps: []step{
{
Line: "var test2, test3 string = \"test_string2\", \"test_string3\"",
Result: "var test2, test3 string = \"test_string2\", \"test_string3\"\n",
},
{
Line: "var test int = 42",
Result: "var test int = 42\n",
},
},
},
{
Name: "Add wrong code",
CodeSteps: []step{
Expand Down Expand Up @@ -89,6 +128,54 @@ var fixtures = []struct {
},
},
},
{
Name: "Meaning of life",
CodeSteps: []step{
{
Line: `
const (
oneConst = 1
tenConst = 10
magicConst = 19
)
`,
Result: "const (\n\toneConst\t= 1\n\ttenConst\t= 10\n\tmagicConst\t= 19\n)\n",
},
{
Line: "var outVar int",
Result: "var outVar int\n",
},
{
Line: `
type MyStruct struct {
counter int
}

func (s *MyStruct) Add() {
s.counter++
}

func (s *MyStruct) Get() int {
return s.counter
}
`,
Result: "type MyStruct struct {\n\tcounter int\n}\nfunc (s *MyStruct) Add() {\n\ts.counter++\n}\nfunc (s *MyStruct) Get() int {\n\treturn s.counter\n}\n",
},
{
Line: `
ms := &MyStruct{counter: 10}

ms.Add()
ms.Add()

outVar = ms.Get() + oneConst + tenConst + magicConst

println(outVar)
`,
Result: "42\n",
},
},
},
}

func TestRepl(t *testing.T) {
Expand All @@ -101,6 +188,7 @@ func TestRepl(t *testing.T) {
if cs.Error == "" {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), cs.Error)
}

Expand Down