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