Skip to content

Commit

Permalink
feat(repl): Add support for new declarations. (gnolang#1044)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajnavarro authored and Doozers committed Aug 31, 2023
1 parent b7a6b0d commit 13cc3c8
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 14 deletions.
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

0 comments on commit 13cc3c8

Please sign in to comment.