From a1f32a0b26dd2fe1fa8f3a2e35bd981223181bf8 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 6 Oct 2014 17:13:52 +0200 Subject: [PATCH 01/11] Solidity scanner and some unit tests. The scanner is a modified version of the v8 javascript scanner. --- CMakeLists.txt | 1 + solidityScanner.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 solidityScanner.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6936addb3..b4d0e46bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth gmp) +target_link_libraries(testeth solidity) target_link_libraries(testeth ${CRYPTOPP_LS}) if ("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/solidityScanner.cpp b/solidityScanner.cpp new file mode 100644 index 000000000..afbcdffae --- /dev/null +++ b/solidityScanner.cpp @@ -0,0 +1,139 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the solidity scanner. + */ + +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +BOOST_AUTO_TEST_SUITE(solidity) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(string_escapes) +{ + Scanner scanner(CharStream(" { \"a\\x61\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); +} + +BOOST_AUTO_TEST_CASE(string_escapes_with_zero) +{ + Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); +} + +BOOST_AUTO_TEST_CASE(string_escape_illegal) +{ + Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); + // TODO recovery from illegal tokens should be improved + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(hex_numbers) +{ + Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), 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(), "0x765432536763762734623472346"); + 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")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 23); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 24); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 25); + BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 26); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 27); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 32); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 50); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(ambiguities) +{ + // test scanning of some operators which need look-ahead + Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.next(), Token::LT); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::INC); + BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); + BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces From 762817f8383b5ddbf4de7f0c3595681e7c89f69a Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 7 Oct 2014 18:25:04 +0200 Subject: [PATCH 02/11] Solidity parser, can not parse much yet. --- solidityParser.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++ solidityScanner.cpp | 37 ++++++++++++++++---------------- 2 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 solidityParser.cpp diff --git a/solidityParser.cpp b/solidityParser.cpp new file mode 100644 index 000000000..f42506767 --- /dev/null +++ b/solidityParser.cpp @@ -0,0 +1,52 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the solidity parser. + */ + +#include + +#include +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +BOOST_AUTO_TEST_SUITE(SolidityParser) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + std::string text = "contract test123 {\n" + "\tuint256 stateVariable1;\n" + "}\n"; + Parser parser; + CharStream str(text); + // @todo: figure out why this does not compile + //Scanner scanner(CharStream(text)); + Scanner scanner(str); + BOOST_CHECK_NO_THROW(parser.parse(scanner)); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces + diff --git a/solidityScanner.cpp b/solidityScanner.cpp index afbcdffae..7f84146a3 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -27,21 +27,26 @@ namespace dev { namespace solidity { namespace test { -BOOST_AUTO_TEST_SUITE(solidity) +BOOST_AUTO_TEST_SUITE(SolidityScanner) + +BOOST_AUTO_TEST_CASE(test_empty) +{ + Scanner scanner(CharStream("")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); +} BOOST_AUTO_TEST_CASE(smoke_test) { Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); @@ -51,26 +56,23 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(string_escapes) { Scanner scanner(CharStream(" { \"a\\x61\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); } BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); } BOOST_AUTO_TEST_CASE(string_escape_illegal) { Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); // TODO recovery from illegal tokens should be improved @@ -83,8 +85,7 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) BOOST_AUTO_TEST_CASE(hex_numbers) { Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::VAR); + 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); @@ -96,8 +97,7 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_AUTO_TEST_CASE(locations) { Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); @@ -122,8 +122,7 @@ BOOST_AUTO_TEST_CASE(ambiguities) { // test scanning of some operators which need look-ahead Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); BOOST_CHECK_EQUAL(scanner.next(), Token::LT); BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); From 9766467f50a5a34776d80744238687fea3fbbec0 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 8 Oct 2014 20:53:50 +0200 Subject: [PATCH 03/11] Parse everything up to function bodies and report parser errors with location. --- solidityParser.cpp | 103 ++++++++++++++++++++++++++++++++++++++++---- solidityScanner.cpp | 24 +++++------ 2 files changed, 106 insertions(+), 21 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index f42506767..91247a3b7 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -30,19 +31,103 @@ namespace dev { namespace solidity { namespace test { +namespace { + ptr parseText(const std::string& _source) + { + Parser parser; + return parser.parse(std::make_shared(CharStream(_source))); + } +} + BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_CASE(smoke_test) { - std::string text = "contract test123 {\n" - "\tuint256 stateVariable1;\n" - "}\n"; - Parser parser; - CharStream str(text); - // @todo: figure out why this does not compile - //Scanner scanner(CharStream(text)); - Scanner scanner(str); - BOOST_CHECK_NO_THROW(parser.parse(scanner)); + char const* text = "contract test {\n" + " uint256 stateVariable1;\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) +{ + char const* text = "contract test {\n" + " uint256 ;\n" + "}\n"; + cwarn << "The next error is expected."; + BOOST_CHECK_THROW(parseText(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(empty_function) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName(hash160 arg1, address addr) const\n" + " returns (int id)\n" + " { }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(no_function_params) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName() {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(single_function_param) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(struct_definition) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " struct MyStructName {\n" + " address addr;\n" + " uint256 count;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping) +{ + char const* text = "contract test {\n" + " mapping(address => string) names;\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping_in_struct) +{ + char const* text = "contract test {\n" + " struct test_struct {\n" + " address addr;\n" + " uint256 count;\n" + " mapping(hash => test_struct) self_reference;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) +{ + char const* text = "contract test {\n" + " struct test_struct {\n" + " address addr;\n" + " mapping (uint64 => mapping (hash => uint)) complex_mapping;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); } diff --git a/solidityScanner.cpp b/solidityScanner.cpp index 7f84146a3..759d2f101 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -98,23 +98,23 @@ BOOST_AUTO_TEST_CASE(locations) { Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 20); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 23); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 24); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 25); + 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().beg_pos, 26); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 27); + 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().beg_pos, 27); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 32); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 45); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 50); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } From 51f335838c4d882e71fe8e09f744f9ed40391e02 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 9 Oct 2014 15:57:49 +0200 Subject: [PATCH 04/11] Initial implementation of Solidity parser finished, not yet tested much. --- solidityParser.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/solidityParser.cpp b/solidityParser.cpp index 91247a3b7..86d09f170 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -130,6 +130,84 @@ BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(variable_definition) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " var b;\n" + " uint256 c;\n" + " mapping(address=>hash) d;\n" + " customtype varname;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " var b = 2;\n" + " uint256 c = 0x87;\n" + " mapping(address=>hash) d;\n" + " string name = \"Solidity\";" + " customtype varname;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(operator_expression) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4) || false && (1 - 12) + -9;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(complex_expression) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4).member(++67)[a/=9] || true;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(while_loop) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4).member(++67) || true;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(if_statement) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " if (a >= 8) return 2; else { var b = 7; }\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(else_if_statement) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) returns (address b) {\n" + " if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + + BOOST_AUTO_TEST_SUITE_END() From 9c9a529b9d08e28a000ba537488aad136bfe9789 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2014 15:07:21 +0200 Subject: [PATCH 05/11] Name resolution. --- solidityNameAndTypeResolution.cpp | 113 ++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 solidityNameAndTypeResolution.cpp diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp new file mode 100644 index 000000000..568025e5a --- /dev/null +++ b/solidityNameAndTypeResolution.cpp @@ -0,0 +1,113 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the name and type resolution of the solidity parser. + */ + +#include + +#include +#include +#include +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +namespace { + void parseTextAndResolveNames(const std::string& _source) + { + Parser parser; + ptr contract = parser.parse( + std::make_shared(CharStream(_source))); + NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*contract); + } +} + +BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* text = "contract test {\n" + " uint256 stateVariable1;\n" + " function fun(uint256 arg1) { var x = 2; uint256 y = 3; x = 1; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " uint128 variable;\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(double_function_declaration) +{ + char const* text = "contract test {\n" + " function fun() { var x = 2; }\n" + " function fun() { var y = 9; }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(double_variable_declaration) +{ + char const* text = "contract test {\n" + " function f() { uint256 x = 9; if (true) { uint256 x = 2;} x = 3; }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(name_shadowing) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { uint8 variable = 2; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(name_references) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { variable = 2; f(); test; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(undeclared_name) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { notfound = 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces + From de155c13efcfa0b88b17fd8eb297b660d99ffcc0 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2014 18:22:15 +0200 Subject: [PATCH 06/11] Type system, not yet complete. --- solidityNameAndTypeResolution.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index 568025e5a..5a938e461 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* text = "contract test {\n" " uint256 stateVariable1;\n" - " function fun(uint256 arg1) { var x = 2; uint256 y = 3; x = 1; }" + " function fun(uint256 arg1) { var x; uint256 y; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -66,8 +66,8 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) BOOST_AUTO_TEST_CASE(double_function_declaration) { char const* text = "contract test {\n" - " function fun() { var x = 2; }\n" - " function fun() { var y = 9; }\n" + " function fun() { var x; }\n" + " function fun() { var x; }\n" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) BOOST_AUTO_TEST_CASE(double_variable_declaration) { char const* text = "contract test {\n" - " function f() { uint256 x = 9; if (true) { uint256 x = 2;} x = 3; }\n" + " function f() { uint256 x; if (true) { uint256 x; } }\n" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(name_shadowing) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { uint8 variable = 2; }" + " function f() { uint32 variable ; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(name_references) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { variable = 2; f(); test; }" + " function f(uint256 arg) returns (uint out) { f(variable); test; out; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { notfound = 2; }" + " function f(uint256 arg) { f(notfound); }" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } From 35383f9b882bdbadb79f5729aca9cf32f7fce17a Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 15 Oct 2014 14:45:51 +0200 Subject: [PATCH 07/11] Added meaningful exception types. --- solidityNameAndTypeResolution.cpp | 9 +++++---- solidityParser.cpp | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index 5a938e461..c9817eb46 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace dev { @@ -60,7 +61,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) " uint256 variable;\n" " uint128 variable;\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(double_function_declaration) @@ -69,7 +70,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) " function fun() { var x; }\n" " function fun() { var x; }\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(double_variable_declaration) @@ -77,7 +78,7 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration) char const* text = "contract test {\n" " function f() { uint256 x; if (true) { uint256 x; } }\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(name_shadowing) @@ -104,7 +105,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) " uint256 variable;\n" " function f(uint256 arg) { f(notfound); }" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_SUITE_END() diff --git a/solidityParser.cpp b/solidityParser.cpp index 86d09f170..b1f27bcb6 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace dev { @@ -54,8 +55,7 @@ BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) char const* text = "contract test {\n" " uint256 ;\n" "}\n"; - cwarn << "The next error is expected."; - BOOST_CHECK_THROW(parseText(text), std::exception); + BOOST_CHECK_THROW(parseText(text), ParserError); } BOOST_AUTO_TEST_CASE(empty_function) From c2f3d27940cb36d1991d2464f36f320d9d656577 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 15 Oct 2014 15:54:41 +0200 Subject: [PATCH 08/11] Some fixes for the type system, should be quite usable now. --- solidityNameAndTypeResolution.cpp | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index c9817eb46..d2f99e83e 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -108,6 +108,64 @@ BOOST_AUTO_TEST_CASE(undeclared_name) BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } +BOOST_AUTO_TEST_CASE(reference_to_later_declaration) +{ + char const* text = "contract test {\n" + " function g() { f(); }" + " function f() { }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_inference_smoke_test) +{ + char const* text = "contract test {\n" + " function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_checking_return) +{ + char const* text = "contract test {\n" + " function f() returns (bool r) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) +{ + char const* text = "contract test {\n" + " function f() returns (bool r1, bool r2) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) +{ + char const* text = "contract test {\n" + " function f() returns (uint256 r) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(type_checking_function_call) +{ + char const* text = "contract test {\n" + " function f() returns (bool r) { return g(12, true) == 3; }\n" + " function g(uint256 a, bool b) returns (uint256 r) { }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) +{ + char const* text = "contract test {\n" + " function f() returns (int256 r) { var x = int256(uint32(2)); return x; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } } } // end namespaces From ee06ed2ff8fab08bc31662c298796c50009c2a11 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 16 Oct 2014 14:08:54 +0200 Subject: [PATCH 09/11] Corrected coding style. --- solidityNameAndTypeResolution.cpp | 32 +++--- solidityParser.cpp | 26 +++-- solidityScanner.cpp | 155 +++++++++++++++--------------- 3 files changed, 115 insertions(+), 98 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index d2f99e83e..ed2cb7b53 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -29,19 +29,23 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ -namespace { - void parseTextAndResolveNames(const std::string& _source) - { - Parser parser; - ptr contract = parser.parse( - std::make_shared(CharStream(_source))); - NameAndTypeResolver resolver; - resolver.resolveNamesAndTypes(*contract); - } +namespace +{ +void parseTextAndResolveNames(const std::string& _source) +{ + Parser parser; + ptr contract = parser.parse( + std::make_shared(CharStream(_source))); + NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*contract); +} } BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) @@ -168,5 +172,7 @@ BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces diff --git a/solidityParser.cpp b/solidityParser.cpp index b1f27bcb6..ef434cc35 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -28,16 +28,20 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ -namespace { - ptr parseText(const std::string& _source) - { - Parser parser; - return parser.parse(std::make_shared(CharStream(_source))); - } +namespace +{ +ptr parseText(const std::string& _source) +{ + Parser parser; + return parser.parse(std::make_shared(CharStream(_source))); +} } BOOST_AUTO_TEST_SUITE(SolidityParser) @@ -211,5 +215,7 @@ BOOST_AUTO_TEST_CASE(else_if_statement) BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces diff --git a/solidityScanner.cpp b/solidityScanner.cpp index 759d2f101..d2a960cfb 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -23,116 +23,121 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ BOOST_AUTO_TEST_SUITE(SolidityScanner) BOOST_AUTO_TEST_CASE(test_empty) { - Scanner scanner(CharStream("")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); + Scanner scanner(CharStream("")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); } BOOST_AUTO_TEST_CASE(smoke_test) { - Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); - BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); - BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); - BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(string_escapes) { - Scanner scanner(CharStream(" { \"a\\x61\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); + Scanner scanner(CharStream(" { \"a\\x61\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); } BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { - Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); + Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); } BOOST_AUTO_TEST_CASE(string_escape_illegal) { - Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); - // TODO recovery from illegal tokens should be improved - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); + // TODO recovery from illegal tokens should be improved + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(hex_numbers) { - Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); - 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(), "0x765432536763762734623472346"); - BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); + 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(), "0x765432536763762734623472346"); + 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")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); - 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().end, 32); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); + 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().end, 32); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(ambiguities) { - // test scanning of some operators which need look-ahead - Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); - BOOST_CHECK_EQUAL(scanner.next(), Token::LT); - BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); - BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::INC); - BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); - BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); + // test scanning of some operators which need look-ahead + Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.next(), Token::LT); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::INC); + BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); + BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); } BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces From c24fa78b21080c254719904c4eaccea24e79a446 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 20 Oct 2014 14:00:37 +0200 Subject: [PATCH 10/11] Pointer type cleanup: Use ASTPointer only for AST nodes and shared_ptr for type pointer. --- solidityNameAndTypeResolution.cpp | 2 +- solidityParser.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index ed2cb7b53..833ae6d4b 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -41,7 +41,7 @@ namespace void parseTextAndResolveNames(const std::string& _source) { Parser parser; - ptr contract = parser.parse( + ASTPointer contract = parser.parse( std::make_shared(CharStream(_source))); NameAndTypeResolver resolver; resolver.resolveNamesAndTypes(*contract); diff --git a/solidityParser.cpp b/solidityParser.cpp index ef434cc35..025cd74d1 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -37,7 +37,7 @@ namespace test namespace { -ptr parseText(const std::string& _source) +ASTPointer parseText(const std::string& _source) { Parser parser; return parser.parse(std::make_shared(CharStream(_source))); From c7a101dec321d5bd6fb0c0875b772527cd69a8b4 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Wed, 22 Oct 2014 22:13:08 +0200 Subject: [PATCH 11/11] bug fix --- vm.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vm.cpp b/vm.cpp index f74076399..36837eea4 100644 --- a/vm.cpp +++ b/vm.cpp @@ -512,12 +512,10 @@ void doTests(json_spirit::mValue& v, bool _fillin) } bytes output; - u256 gas; + VM vm(fev.gas); try { - VM vm(fev.gas); output = vm.go(fev).toVector(); - gas = vm.gas(); // Get the remaining gas } catch (Exception const& _e) { @@ -554,7 +552,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) o["post"] = mValue(fev.exportState()); o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); - fev.push(o, "gas", gas); + fev.push(o, "gas", vm.gas()); } else { @@ -578,7 +576,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK_EQUAL(test.toInt(o["gas"]), gas); + BOOST_CHECK_EQUAL(test.toInt(o["gas"]), vm.gas()); auto& expectedAddrs = test.addresses; auto& resultAddrs = fev.addresses; @@ -657,11 +655,13 @@ void executeTests(const string& _name) if (ptestPath == NULL) { cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; - testPath = "../../../tests/vmtests"; + testPath = "../../../tests"; } else testPath = ptestPath; + testPath += "/vmtests"; + #ifdef FILL_TESTS try { @@ -690,7 +690,7 @@ void executeTests(const string& _name) cnote << "Testing VM..." << _name; json_spirit::mValue v; string s = asString(contents(testPath + "/" + _name + ".json")); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); json_spirit::read_string(s, v); dev::test::doTests(v, false); }