diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 06dacd81b..04e47430a 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -236,7 +236,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { switch t := n.Lhs[i].(type) { case *ast.Ident: switch n.Tok { - case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN: + case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN: c.emitLoadLocal(t.Name) ast.Walk(c, n.Rhs[0]) // can only add assign to 1 expr on the RHS c.convertToken(n.Tok) @@ -751,6 +751,8 @@ func (c *codegen) convertToken(tok token.Token) { emitOpcode(c.prog.BinWriter, opcode.MUL) case token.QUO_ASSIGN: emitOpcode(c.prog.BinWriter, opcode.DIV) + case token.REM_ASSIGN: + emitOpcode(c.prog.BinWriter, opcode.MOD) case token.ADD: emitOpcode(c.prog.BinWriter, opcode.ADD) case token.SUB: @@ -759,6 +761,8 @@ func (c *codegen) convertToken(tok token.Token) { emitOpcode(c.prog.BinWriter, opcode.MUL) case token.QUO: emitOpcode(c.prog.BinWriter, opcode.DIV) + case token.REM: + emitOpcode(c.prog.BinWriter, opcode.MOD) case token.LSS: emitOpcode(c.prog.BinWriter, opcode.LT) case token.LEQ: diff --git a/pkg/compiler/codegen_test.go b/pkg/compiler/codegen_test.go new file mode 100644 index 000000000..369b71caa --- /dev/null +++ b/pkg/compiler/codegen_test.go @@ -0,0 +1,72 @@ +package compiler + +import ( + "go/token" + "testing" + + "github.com/CityOfZion/neo-go/pkg/io" + "github.com/CityOfZion/neo-go/pkg/vm/opcode" + "github.com/stretchr/testify/assert" +) + +func TestConvertToken(t *testing.T) { + type testCase struct { + name string + token token.Token + opcode opcode.Opcode + } + + testCases := []testCase{ + {"ADD", + token.ADD, + opcode.ADD, + }, + {"SUB", + token.SUB, + opcode.SUB, + }, + {"MUL", + token.MUL, + opcode.MUL, + }, + {"QUO", + token.QUO, + opcode.DIV, + }, + {"REM", + token.REM, + opcode.MOD, + }, + {"ADD_ASSIGN", + token.ADD_ASSIGN, + opcode.ADD, + }, + {"SUB_ASSIGN", + token.SUB_ASSIGN, + opcode.SUB, + }, + {"MUL_ASSIGN", + token.MUL_ASSIGN, + opcode.MUL, + }, + {"QUO_ASSIGN", + token.QUO_ASSIGN, + opcode.DIV, + }, + {"REM_ASSIGN", + token.REM_ASSIGN, + opcode.MOD, + }, + } + + for _, tcase := range testCases { + t.Run(tcase.name, func(t *testing.T) { eval(t, tcase.token, tcase.opcode) }) + } +} + +func eval(t *testing.T, token token.Token, opcode opcode.Opcode) { + codegen := &codegen{prog: io.NewBufBinWriter()} + codegen.convertToken(token) + readOpcode := codegen.prog.Bytes() + assert.Equal(t, []byte{byte(opcode)}, readOpcode) +} diff --git a/pkg/vm/tests/binary_expr_test.go b/pkg/vm/tests/binary_expr_test.go index 257132bff..3cf5c242d 100644 --- a/pkg/vm/tests/binary_expr_test.go +++ b/pkg/vm/tests/binary_expr_test.go @@ -39,6 +39,17 @@ var binaryExprTestCases = []testCase{ `, big.NewInt(1), }, + { + "simple mod", + ` + package testcase + func Main() int { + x := 3 % 2 + return x + } + `, + big.NewInt(1), + }, { "simple mul", ` @@ -186,6 +197,66 @@ var binaryExprTestCases = []testCase{ `, big.NewInt(1), }, + { + "simple add and assign", + ` + package testcase + func Main() int { + x := 2 + x += 1 + return x + } + `, + big.NewInt(3), + }, + { + "simple sub and assign", + ` + package testcase + func Main() int { + x := 2 + x -= 1 + return x + } + `, + big.NewInt(1), + }, + { + "simple mul and assign", + ` + package testcase + func Main() int { + x := 2 + x *= 2 + return x + } + `, + big.NewInt(4), + }, + { + "simple div and assign", + ` + package testcase + func Main() int { + x := 2 + x /= 2 + return x + } + `, + big.NewInt(1), + }, + { + "simple mod and assign", + ` + package testcase + func Main() int { + x := 5 + x %= 2 + return x + } + `, + big.NewInt(1), + }, } func TestBinaryExprs(t *testing.T) {