From e22cad4d35559cb76449a215ca519f9c0b812c7a Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 4 Nov 2014 15:07:33 +0100 Subject: Tests for type conversion at comparison. --- solidityNameAndTypeResolution.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index 9e34e6d0..f46ad673 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -162,6 +162,22 @@ BOOST_AUTO_TEST_CASE(type_checking_function_call) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(type_conversion_for_comparison) +{ + char const* text = "contract test {\n" + " function f() { uint32(2) == int64(2); }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) +{ + char const* text = "contract test {\n" + " function f() { int32(2) == uint64(2); }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) { char const* text = "contract test {\n" -- cgit From 010710353a4097f5dc94e42130ce22e6f0c72beb Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 4 Nov 2014 19:13:03 +0100 Subject: Proper type promotion and conversion. --- solidityEndToEndTest.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp index b28b8499..b4da53ba 100644 --- a/solidityEndToEndTest.cpp +++ b/solidityEndToEndTest.cpp @@ -219,7 +219,33 @@ BOOST_AUTO_TEST_CASE(short_circuiting) BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(8))); } -//@todo test smaller types +BOOST_AUTO_TEST_CASE(high_bits_cleaning) +{ + char const* sourceCode = "contract test {\n" + " function run() returns(uint256 y) {\n" + " uint32 x = uint32(0xffffffff) + 10;\n" + " if (x >= 0xffffffff) return 0;\n" + " return x;" + " }\n" + "}\n"; + ExecutionFramework framework; + framework.compileAndRun(sourceCode); + BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(9))); +} + +BOOST_AUTO_TEST_CASE(sign_extension) +{ + char const* sourceCode = "contract test {\n" + " function run() returns(uint256 y) {\n" + " int64 x = -int32(0xff);\n" + " if (x >= 0xff) return 0;\n" + " return -uint256(x);" + " }\n" + "}\n"; + ExecutionFramework framework; + framework.compileAndRun(sourceCode); + BOOST_CHECK(framework.callFunction(0, bytes()) == bytes(32, 0xff)); +} BOOST_AUTO_TEST_SUITE_END() -- cgit From 04e7977ea13fcac51e274f867ec1cd664a723bc7 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 4 Nov 2014 21:29:36 +0100 Subject: Type promotion fixes and tests. --- solidityCompiler.cpp | 8 ++++---- solidityEndToEndTest.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- solidityExpressionCompiler.cpp | 33 ++++++++++++++++++--------------- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/solidityCompiler.cpp b/solidityCompiler.cpp index 69d33133..192fd61a 100644 --- a/solidityCompiler.cpp +++ b/solidityCompiler.cpp @@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers) byte(Instruction::JUMPDEST), // beginning of g byte(Instruction::PUSH1), 0x0, byte(Instruction::DUP1), // initialized e and h - byte(Instruction::PUSH1), byte(0x20 + shift), // ret address - byte(Instruction::PUSH1), 0x1, - byte(Instruction::PUSH1), 0x2, - byte(Instruction::PUSH1), 0x3, + byte(Instruction::PUSH1), 0x29 + shift, // ret address + byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), + byte(Instruction::PUSH1), 0x2, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), + byte(Instruction::PUSH1), 0x3, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), byte(Instruction::PUSH1), byte(0x1 + shift), // stack here: ret e h 0x20 1 2 3 0x1 byte(Instruction::JUMP), diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp index b4da53ba..c60d6887 100644 --- a/solidityEndToEndTest.cpp +++ b/solidityEndToEndTest.cpp @@ -192,6 +192,21 @@ BOOST_AUTO_TEST_CASE(many_local_variables) == toBigEndian(u256(0x121121))); } +BOOST_AUTO_TEST_CASE(packing_unpacking_types) +{ + char const* sourceCode = "contract test {\n" + " function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n" + " if (a) y = 1;\n" + " y = y * 0x100000000 | ~b;\n" + " y = y * 0x10000000000000000 | ~c;\n" + " }\n" + "}\n"; + ExecutionFramework framework; + framework.compileAndRun(sourceCode); + BOOST_CHECK(framework.callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) + == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); +} + BOOST_AUTO_TEST_CASE(multiple_return_values) { char const* sourceCode = "contract test {\n" @@ -244,7 +259,32 @@ BOOST_AUTO_TEST_CASE(sign_extension) "}\n"; ExecutionFramework framework; framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()) == bytes(32, 0xff)); + BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(0xff))); +} + +BOOST_AUTO_TEST_CASE(small_unsigned_types) +{ + char const* sourceCode = "contract test {\n" + " function run() returns(uint256 y) {\n" + " uint32 x = uint32(0xffffff) * 0xffffff;\n" + " return x / 0x100;" + " }\n" + "}\n"; + ExecutionFramework framework; + framework.compileAndRun(sourceCode); + BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(0xfffe0000))); +} + +BOOST_AUTO_TEST_CASE(small_signed_types) +{ + char const* sourceCode = "contract test {\n" + " function run() returns(int256 y) {\n" + " return -int32(10) * -int64(20);\n" + " }\n" + "}\n"; + ExecutionFramework framework; + framework.compileAndRun(sourceCode); + BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(200))); } BOOST_AUTO_TEST_SUITE_END() diff --git a/solidityExpressionCompiler.cpp b/solidityExpressionCompiler.cpp index 561cc3bd..3be909c3 100644 --- a/solidityExpressionCompiler.cpp +++ b/solidityExpressionCompiler.cpp @@ -154,8 +154,8 @@ BOOST_AUTO_TEST_CASE(comparison) "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, - byte(eth::Instruction::PUSH2), 0x11, 0xaa, + bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND), + byte(eth::Instruction::PUSH2), 0x11, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::GT), byte(eth::Instruction::PUSH1), 0x1, byte(eth::Instruction::EQ), @@ -172,16 +172,16 @@ BOOST_AUTO_TEST_CASE(short_circuiting) bytes expectation({byte(eth::Instruction::PUSH1), 0xa, byte(eth::Instruction::PUSH1), 0x8, - byte(eth::Instruction::ADD), - byte(eth::Instruction::PUSH1), 0x4, + byte(eth::Instruction::ADD), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), + byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::GT), byte(eth::Instruction::ISZERO), // after this we have 10 + 8 >= 4 byte(eth::Instruction::DUP1), - byte(eth::Instruction::PUSH1), 0x14, + byte(eth::Instruction::PUSH1), 0x20, byte(eth::Instruction::JUMPI), // short-circuit if it is true byte(eth::Instruction::POP), - byte(eth::Instruction::PUSH1), 0x2, - byte(eth::Instruction::PUSH1), 0x9, + byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), + byte(eth::Instruction::PUSH1), 0x9, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::EQ), byte(eth::Instruction::ISZERO), // after this we have 2 != 9 byte(eth::Instruction::JUMPDEST), @@ -197,10 +197,11 @@ BOOST_AUTO_TEST_CASE(arithmetics) " function f() { var x = (1 * (2 / (3 % (4 + (5 - (6 | (7 & (8 ^ 9)))))))); }" "}\n"; bytes code = compileFirstExpression(sourceCode); - bytes expectation({byte(eth::Instruction::PUSH1), 0x1, byte(eth::Instruction::PUSH1), 0x2, + byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::PUSH1), 0x3, + byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0x5, byte(eth::Instruction::PUSH1), 0x6, @@ -213,8 +214,10 @@ BOOST_AUTO_TEST_CASE(arithmetics) byte(eth::Instruction::SWAP1), byte(eth::Instruction::SUB), byte(eth::Instruction::ADD), + byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::SWAP1), byte(eth::Instruction::MOD), + byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::SWAP1), byte(eth::Instruction::DIV), byte(eth::Instruction::MUL)}); @@ -231,8 +234,8 @@ BOOST_AUTO_TEST_CASE(unary_operators) bytes expectation({byte(eth::Instruction::PUSH1), 0x1, byte(eth::Instruction::PUSH1), 0x0, byte(eth::Instruction::SUB), - byte(eth::Instruction::NOT), - byte(eth::Instruction::PUSH1), 0x2, + byte(eth::Instruction::NOT), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), + byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::EQ), byte(eth::Instruction::ISZERO)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); @@ -305,7 +308,7 @@ BOOST_AUTO_TEST_CASE(assignment) byte(eth::Instruction::POP), byte(eth::Instruction::DUP2), // Stack here: a+b b a+b - byte(eth::Instruction::PUSH1), 0x2, + byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::MUL)}); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } @@ -320,17 +323,17 @@ BOOST_AUTO_TEST_CASE(function_call) {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b - bytes expectation({byte(eth::Instruction::PUSH1), 0x0a, + bytes expectation({byte(eth::Instruction::PUSH1), 0x0d, byte(eth::Instruction::DUP3), - byte(eth::Instruction::PUSH1), 0x01, + byte(eth::Instruction::PUSH1), 0x01, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::ADD), // Stack here: a b (a+1) byte(eth::Instruction::DUP3), - byte(eth::Instruction::PUSH1), 0x14, + byte(eth::Instruction::PUSH1), 0x1a, byte(eth::Instruction::JUMP), byte(eth::Instruction::JUMPDEST), // Stack here: a b g(a+1, b) - byte(eth::Instruction::PUSH1), 0x02, + byte(eth::Instruction::PUSH1), 0x02, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), byte(eth::Instruction::MUL), // Stack here: a b g(a+1, b)*2 byte(eth::Instruction::DUP3), -- cgit From b9cc3baf40f7235b0c4302742f294e6228cff070 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 6 Nov 2014 01:39:59 +0100 Subject: Fixes for test framework (sign the transaction). --- solidityEndToEndTest.cpp | 111 +++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 62 deletions(-) diff --git a/solidityEndToEndTest.cpp b/solidityEndToEndTest.cpp index c60d6887..dc8d34cb 100644 --- a/solidityEndToEndTest.cpp +++ b/solidityEndToEndTest.cpp @@ -41,31 +41,31 @@ class ExecutionFramework public: ExecutionFramework() { g_logVerbosity = 0; } - bytes compileAndRun(std::string const& _sourceCode) + bytes const& compileAndRun(std::string const& _sourceCode) { bytes code = dev::solidity::CompilerStack::compile(_sourceCode); sendMessage(code, true); + BOOST_REQUIRE(!m_output.empty()); return m_output; } - bytes callFunction(byte _index, bytes const& _data) + bytes const& callFunction(byte _index, bytes const& _data) { sendMessage(bytes(1, _index) + _data, false); return m_output; } - bytes callFunction(byte _index, u256 const& _argument1) + bytes const& callFunction(byte _index, u256 const& _argument1) { - callFunction(_index, toBigEndian(_argument1)); - return m_output; + return callFunction(_index, toBigEndian(_argument1)); } private: void sendMessage(bytes const& _data, bool _isCreation) { eth::Executive executive(m_state); - eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data) - : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data); + eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) + : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); bytes transactionRLP = t.rlp(); try { @@ -77,13 +77,14 @@ private: { BOOST_REQUIRE(!executive.create(Address(), 0, m_gasPrice, m_gas, &_data, Address())); m_contractAddress = executive.newAddress(); + BOOST_REQUIRE(m_contractAddress); BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); } else BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address())); BOOST_REQUIRE(executive.go()); executive.finalize(); - m_output = executive.out().toBytes(); + m_output = executive.out().toVector(); } Address m_contractAddress; @@ -93,27 +94,24 @@ private: bytes m_output; }; -BOOST_AUTO_TEST_SUITE(SolidityCompilerEndToEndTest) +BOOST_FIXTURE_TEST_SUITE(SolidityCompilerEndToEndTest, ExecutionFramework) BOOST_AUTO_TEST_CASE(smoke_test) { char const* sourceCode = "contract test {\n" " function f(uint a) returns(uint d) { return a * 7; }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); + compileAndRun(sourceCode); u256 a = 0x200030004; - bytes result = framework.callFunction(0, a); - BOOST_CHECK(result == toBigEndian(a * 7)); + BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7)); } BOOST_AUTO_TEST_CASE(empty_contract) { char const* sourceCode = "contract test {\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()).empty()); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()).empty()); } BOOST_AUTO_TEST_CASE(recursive_calls) @@ -124,13 +122,12 @@ BOOST_AUTO_TEST_CASE(recursive_calls) " else return n * f(n - 1);\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2))); - BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6))); - BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2))); + BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6))); + BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24))); } BOOST_AUTO_TEST_CASE(while_loop) @@ -142,13 +139,12 @@ BOOST_AUTO_TEST_CASE(while_loop) " while (i <= n) nfac *= i++;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2))); - BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6))); - BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2))); + BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6))); + BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24))); } BOOST_AUTO_TEST_CASE(calling_other_functions) @@ -168,13 +164,12 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) " return 3 * x + 1;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(2, u256(0)) == toBigEndian(u256(0))); - BOOST_CHECK(framework.callFunction(2, u256(1)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(2, u256(2)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(2, u256(8)) == toBigEndian(u256(1))); - BOOST_CHECK(framework.callFunction(2, u256(127)) == toBigEndian(u256(1))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(2, u256(0)) == toBigEndian(u256(0))); + BOOST_CHECK(callFunction(2, u256(1)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(2, u256(2)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(2, u256(8)) == toBigEndian(u256(1))); + BOOST_CHECK(callFunction(2, u256(127)) == toBigEndian(u256(1))); } BOOST_AUTO_TEST_CASE(many_local_variables) @@ -186,9 +181,8 @@ BOOST_AUTO_TEST_CASE(many_local_variables) " y += b + x2;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000))) + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000))) == toBigEndian(u256(0x121121))); } @@ -201,9 +195,8 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) " y = y * 0x10000000000000000 | ~c;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); } @@ -214,9 +207,8 @@ BOOST_AUTO_TEST_CASE(multiple_return_values) " y1 = x2; y2 = x1;\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) == toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0))); } @@ -228,10 +220,9 @@ BOOST_AUTO_TEST_CASE(short_circuiting) " return x;" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0))); - BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(8))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(0))); + BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(8))); } BOOST_AUTO_TEST_CASE(high_bits_cleaning) @@ -243,9 +234,8 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) " return x;" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(9))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(9))); } BOOST_AUTO_TEST_CASE(sign_extension) @@ -257,9 +247,8 @@ BOOST_AUTO_TEST_CASE(sign_extension) " return -uint256(x);" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(0xff))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xff))); } BOOST_AUTO_TEST_CASE(small_unsigned_types) @@ -270,9 +259,8 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) " return x / 0x100;" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(0xfffe0000))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xfe0000))); } BOOST_AUTO_TEST_CASE(small_signed_types) @@ -282,9 +270,8 @@ BOOST_AUTO_TEST_CASE(small_signed_types) " return -int32(10) * -int64(20);\n" " }\n" "}\n"; - ExecutionFramework framework; - framework.compileAndRun(sourceCode); - BOOST_CHECK(framework.callFunction(0, bytes()) == toBigEndian(u256(200))); + compileAndRun(sourceCode); + BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(200))); } BOOST_AUTO_TEST_SUITE_END() -- cgit From 08cba0653f781dec66b3211990506066a48390c2 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 08:40:21 +0100 Subject: Support for negative literals. --- solidityExpressionCompiler.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- solidityScanner.cpp | 26 ++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/solidityExpressionCompiler.cpp b/solidityExpressionCompiler.cpp index 3be909c3..8fc4a1a2 100644 --- a/solidityExpressionCompiler.cpp +++ b/solidityExpressionCompiler.cpp @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(arithmetics) BOOST_AUTO_TEST_CASE(unary_operators) { char const* sourceCode = "contract test {\n" - " function f() { var x = !(~+-1 == 2); }" + " function f() { var x = !(~+- 1 == 2); }" "}\n"; bytes code = compileFirstExpression(sourceCode); @@ -347,6 +347,45 @@ BOOST_AUTO_TEST_CASE(function_call) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE(negative_literals_8bits) +{ + // these all fit in 8 bits + char const* sourceCode = "contract test {\n" + " function f() { int8 x = -0 + -1 + -0x01 + -127 + -128; }\n" + "}\n"; + bytes code = compileFirstExpression(sourceCode); + + bytes expectation(bytes({byte(eth::Instruction::PUSH1), 0x00, + byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + + bytes({byte(eth::Instruction::ADD), + byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + + bytes({byte(eth::Instruction::ADD), + byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x81) + + bytes({byte(eth::Instruction::ADD), + byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80) + + bytes({byte(eth::Instruction::ADD)})); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + +BOOST_AUTO_TEST_CASE(negative_literals_16bits) +{ + // -1 should need 8 bits, -129 should need 16 bits, how many bits are used is visible + // from the SIGNEXTEND opcodes + char const* sourceCode = "contract test {\n" + " function f() { int64 x = int64(-1 + -129); }\n" + "}\n"; + bytes code = compileFirstExpression(sourceCode); + + bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + + bytes({byte(eth::Instruction::PUSH1), 0x00, + byte(eth::Instruction::SIGNEXTEND), + byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x7f) + + bytes({byte(eth::Instruction::ADD), + byte(eth::Instruction::PUSH1), 0x01, + byte(eth::Instruction::SIGNEXTEND)})); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/solidityScanner.cpp b/solidityScanner.cpp index d2a960cf..d714699a 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -97,6 +97,27 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } +BOOST_AUTO_TEST_CASE(negative_numbers) +{ + Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-.2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-0x78"); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-7.3"); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "8.9"); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + BOOST_AUTO_TEST_CASE(locations) { Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); @@ -109,11 +130,8 @@ BOOST_AUTO_TEST_CASE(locations) BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); - BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); -- cgit