mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Function hoister.
This commit is contained in:
		
							parent
							
								
									7614b16dc9
								
							
						
					
					
						commit
						99c8ed075e
					
				
							
								
								
									
										59
									
								
								libjulia/optimiser/FunctionHoister.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libjulia/optimiser/FunctionHoister.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | /*
 | ||||||
|  | 	This file is part of solidity. | ||||||
|  | 
 | ||||||
|  | 	solidity 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. | ||||||
|  | 
 | ||||||
|  | 	solidity 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 solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /**
 | ||||||
|  |  * Optimiser component that changes the code so that it consists of a block starting with | ||||||
|  |  * a single block followed only by function definitions and with no functions defined | ||||||
|  |  * anywhere else. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <libjulia/optimiser/FunctionHoister.h> | ||||||
|  | 
 | ||||||
|  | #include <libsolidity/inlineasm/AsmData.h> | ||||||
|  | 
 | ||||||
|  | #include <libsolidity/interface/Exceptions.h> | ||||||
|  | 
 | ||||||
|  | #include <libdevcore/CommonData.h> | ||||||
|  | 
 | ||||||
|  | #include <boost/range/algorithm_ext/erase.hpp> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev; | ||||||
|  | using namespace dev::julia; | ||||||
|  | using namespace dev::solidity; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void FunctionHoister::operator()(Block& _block) | ||||||
|  | { | ||||||
|  | 	bool topLevel = m_isTopLevel; | ||||||
|  | 	m_isTopLevel = false; | ||||||
|  | 	for (auto&& statement: _block.statements) | ||||||
|  | 	{ | ||||||
|  | 		boost::apply_visitor(*this, statement); | ||||||
|  | 		if (statement.type() == typeid(FunctionDefinition)) | ||||||
|  | 		{ | ||||||
|  | 			m_functions.emplace_back(std::move(statement)); | ||||||
|  | 			statement = Block{_block.location, {}}; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	auto isEmptyBlock = [](Statement const& _st) -> bool { | ||||||
|  | 		return _st.type() == typeid(Block) && boost::get<Block>(_st).statements.empty(); | ||||||
|  | 	}; | ||||||
|  | 	// Remove empty blocks
 | ||||||
|  | 	boost::range::remove_erase_if(_block.statements, isEmptyBlock); | ||||||
|  | 	if (topLevel) | ||||||
|  | 		_block.statements += std::move(m_functions); | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								libjulia/optimiser/FunctionHoister.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								libjulia/optimiser/FunctionHoister.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | /*
 | ||||||
|  | 	This file is part of solidity. | ||||||
|  | 
 | ||||||
|  | 	solidity 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. | ||||||
|  | 
 | ||||||
|  | 	solidity 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 solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /**
 | ||||||
|  |  * Optimiser component that changes the code so that all function definitions are at the top | ||||||
|  |  * level block. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <libjulia/ASTDataForward.h> | ||||||
|  | 
 | ||||||
|  | #include <libjulia/optimiser/ASTWalker.h> | ||||||
|  | 
 | ||||||
|  | namespace dev | ||||||
|  | { | ||||||
|  | namespace julia | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Moves all functions to the top-level scope. | ||||||
|  |  * Applying this transformation to source code that has ambiguous identifiers might | ||||||
|  |  * lead to invalid code. | ||||||
|  |  * | ||||||
|  |  * Prerequisites: Disambiguator | ||||||
|  |  */ | ||||||
|  | class FunctionHoister: public ASTModifier | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	using ASTModifier::operator(); | ||||||
|  | 	virtual void operator()(Block& _block); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	bool m_isTopLevel = true; | ||||||
|  | 	std::vector<Statement> m_functions; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										85
									
								
								test/libjulia/FunctionHoister.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								test/libjulia/FunctionHoister.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | |||||||
|  | /*
 | ||||||
|  |     This file is part of solidity. | ||||||
|  | 
 | ||||||
|  |     solidity 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. | ||||||
|  | 
 | ||||||
|  |     solidity 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 solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /**
 | ||||||
|  |  * @date 2017 | ||||||
|  |  * Unit tests for the iulia function hoister. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <test/libjulia/Common.h> | ||||||
|  | 
 | ||||||
|  | #include <libjulia/optimiser/FunctionHoister.h> | ||||||
|  | 
 | ||||||
|  | #include <libsolidity/inlineasm/AsmPrinter.h> | ||||||
|  | 
 | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev::julia; | ||||||
|  | using namespace dev::julia::test; | ||||||
|  | using namespace dev::solidity; | ||||||
|  | 
 | ||||||
|  | #define CHECK(_original, _expectation)\ | ||||||
|  | do\ | ||||||
|  | {\ | ||||||
|  | 	assembly::AsmPrinter p(true);\ | ||||||
|  | 	Block b = disambiguate(_original);\ | ||||||
|  | 	(FunctionHoister{})(b);\ | ||||||
|  | 	string result = p(b);\ | ||||||
|  | 	BOOST_CHECK_EQUAL(result, format(_expectation));\ | ||||||
|  | }\ | ||||||
|  | while(false) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(IuliaFunctionHoister) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(smoke_test) | ||||||
|  | { | ||||||
|  | 	CHECK("{ }", "{ }"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(single_fun) | ||||||
|  | { | ||||||
|  | 	CHECK( | ||||||
|  | 		"{ let a:u256 function f() {} }", | ||||||
|  | 		"{ let a:u256 function f() {} }" | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multi_fun_mixed) | ||||||
|  | { | ||||||
|  | 	CHECK( | ||||||
|  | 		"{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", | ||||||
|  | 		"{ let a:u256 let c:u256 let e:u256 function f() { let b:u256 } function g() { let d:u256 } }" | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(nested_fun) | ||||||
|  | { | ||||||
|  | 	CHECK( | ||||||
|  | 		"{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", | ||||||
|  | 		"{ let a:u256 function g() { let c:u256 } function f() { let b:u256 let d:u256 } }" | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(empty_block) | ||||||
|  | { | ||||||
|  | 	CHECK( | ||||||
|  | 		"{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", | ||||||
|  | 		"{ let a:u256 function f() -> x:bool { let b:u256 := 4:u256 for {} f() {} {} } }" | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user