diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 37b590b1c4c..751534e1e16 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -39,6 +39,75 @@ func main() { m.RunMain() } +func TestDoOpEvalBaseConversion(t *testing.T) { + m := NewMachine("test", nil) + + type testCase struct { + input string + expect string + expectErr bool + } + + testCases := []testCase{ + // binary + {input: "0b101010", expect: "42", expectErr: false}, + {input: "0B101010", expect: "42", expectErr: false}, + {input: "0b111111111111111111111111111111111111111111111111111111111111111", expect: "9223372036854775807", expectErr: false}, + {input: "0b0", expect: "0", expectErr: false}, + {input: "0b000000101010", expect: "42", expectErr: false}, + {input: " 0b101010", expectErr: true}, + {input: "0b", expectErr: true}, + {input: "0bXXXX", expectErr: true}, + {input: "42b0", expectErr: true}, + // octal + {input: "0o42", expect: "34", expectErr: false}, + {input: "0o0", expect: "0", expectErr: false}, + {input: "042", expect: "34", expectErr: false}, + {input: "0777", expect: "511", expectErr: false}, + {input: "0O0000042", expect: "34", expectErr: false}, + {input: "0777777777777777777777", expect: "9223372036854775807", expectErr: false}, + {input: "0o777777777777777777777", expect: "9223372036854775807", expectErr: false}, + {input: "048", expectErr: true}, + {input: "0o", expectErr: true}, + {input: "0oXXXX", expectErr: true}, + {input: "0OXXXX", expectErr: true}, + {input: "0o42x42", expectErr: true}, + {input: "0O42x42", expectErr: true}, + {input: "0420x42", expectErr: true}, + {input: "0o420o42", expectErr: true}, + // hex + {input: "0x2a", expect: "42", expectErr: false}, + {input: "0X2A", expect: "42", expectErr: false}, + {input: "0x7FFFFFFFFFFFFFFF", expect: "9223372036854775807", expectErr: false}, + {input: "0x2a ", expectErr: true}, + {input: "0x", expectErr: true}, + {input: "0xXXXX", expectErr: true}, + {input: "0xGHIJ", expectErr: true}, + {input: "0x42o42", expectErr: true}, + {input: "0x2ax42", expectErr: true}, + // decimal + {input: "42", expect: "42", expectErr: false}, + {input: "0", expect: "0", expectErr: false}, + {input: "0000000000", expect: "0", expectErr: false}, + {input: "9223372036854775807", expect: "9223372036854775807", expectErr: false}, + } + + for _, tc := range testCases { + m.PushExpr(&BasicLitExpr{ + Kind: INT, + Value: tc.input, + }) + + if tc.expectErr { + assert.Panics(t, func() { m.doOpEval() }) + } else { + m.doOpEval() + v := m.PopValue() + assert.Equal(t, v.V.String(), tc.expect) + } + } +} + func TestEval(t *testing.T) { t.Parallel() diff --git a/gnovm/pkg/gnolang/op_eval.go b/gnovm/pkg/gnolang/op_eval.go index 83dd3737b6b..3eadbeabfc9 100644 --- a/gnovm/pkg/gnolang/op_eval.go +++ b/gnovm/pkg/gnolang/op_eval.go @@ -47,8 +47,8 @@ func (m *Machine) doOpEval() { bi := big.NewInt(0) // TODO optimize. // TODO deal with base. - if len(x.Value) > 2 && x.Value[0] == '0' { - var ok bool = false + var ok bool + if len(x.Value) >= 2 && x.Value[0] == '0' { switch x.Value[1] { case 'b', 'B': _, ok = bi.SetString(x.Value[2:], 2) @@ -56,6 +56,8 @@ func (m *Machine) doOpEval() { _, ok = bi.SetString(x.Value[2:], 8) case 'x', 'X': _, ok = bi.SetString(x.Value[2:], 16) + case '0', '1', '2', '3', '4', '5', '6', '7': + _, ok = bi.SetString(x.Value, 8) default: ok = false } diff --git a/gnovm/tests/files/base_conv0.gno b/gnovm/tests/files/base_conv0.gno new file mode 100644 index 00000000000..381d10cdc98 --- /dev/null +++ b/gnovm/tests/files/base_conv0.gno @@ -0,0 +1,27 @@ +package main + +func main() { + // binary + println(0b1010) + println(0B1010) + + // decimal + println(10) + + // octal + println(0o12) + println(012) + + // hex + println(0xA) + println(0xa) +} + +// Output: +// 10 +// 10 +// 10 +// 10 +// 10 +// 10 +// 10 diff --git a/gnovm/tests/files/base_conv1.gno b/gnovm/tests/files/base_conv1.gno new file mode 100644 index 00000000000..6ccf8d0fe70 --- /dev/null +++ b/gnovm/tests/files/base_conv1.gno @@ -0,0 +1,27 @@ +package main + +func main() { + // binary + println(-0b1010) + println(-0B1010) + + // decimal + println(-10) + + // octal + println(-0o12) + println(-012) + + // hex + println(-0xA) + println(-0xa) +} + +// Output: +// -10 +// -10 +// -10 +// -10 +// -10 +// -10 +// -10