mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Traverse object tree
This commit is contained in:
		
							parent
							
								
									e61843428a
								
							
						
					
					
						commit
						3b2805b760
					
				@ -144,8 +144,36 @@ std::set<YulString> Object::qualifiedDataNames() const
 | 
				
			|||||||
	return qualifiedNames;
 | 
						return qualifiedNames;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Object::traverseObjectTree(Object const* _object, YulString _qualifiedName, std::function<bool(Object const*)> _visitor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						yulAssert(!_qualifiedName.empty(), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::vector<std::string> subObjectPathComponents;
 | 
				
			||||||
 | 
						boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of("."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (std::string const& currentSubObjectName: subObjectPathComponents)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							yulAssert(!currentSubObjectName.empty(), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto subObjectIt = ranges::find_if(
 | 
				
			||||||
 | 
								_object->subObjects,
 | 
				
			||||||
 | 
								[¤tSubObjectName](auto const& _subObject) { return _subObject->name.str() == currentSubObjectName; }
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (subObjectIt != _object->subObjects.end())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								_object = dynamic_cast<Object const*>(subObjectIt->get());
 | 
				
			||||||
 | 
								yulAssert(_object, "Assembly object <" + _object->name.str() + "> not found or does not contain code.");
 | 
				
			||||||
 | 
								yulAssert(_object->subId != std::numeric_limits<size_t>::max(), "");
 | 
				
			||||||
 | 
								if (_visitor(_object))
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
 | 
					std::vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						std::vector<size_t> path;
 | 
				
			||||||
	yulAssert(_qualifiedName != name, "");
 | 
						yulAssert(_qualifiedName != name, "");
 | 
				
			||||||
	yulAssert(subIndexByName.count(name) == 0, "");
 | 
						yulAssert(subIndexByName.count(name) == 0, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -153,49 +181,24 @@ std::vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
 | 
				
			|||||||
		_qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)};
 | 
							_qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)};
 | 
				
			||||||
	yulAssert(!_qualifiedName.empty(), "");
 | 
						yulAssert(!_qualifiedName.empty(), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::vector<std::string> subObjectPathComponents;
 | 
						traverseObjectTree(this, _qualifiedName, [&](Object const* _object) -> bool {
 | 
				
			||||||
	boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of("."));
 | 
							path.push_back({_object->subId});
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
	std::vector<size_t> path;
 | 
						});
 | 
				
			||||||
	Object const* object = this;
 | 
					 | 
				
			||||||
	for (std::string const& currentSubObjectName: subObjectPathComponents)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		yulAssert(!currentSubObjectName.empty(), "");
 | 
					 | 
				
			||||||
		auto subIndexIt = object->subIndexByName.find(YulString{currentSubObjectName});
 | 
					 | 
				
			||||||
		yulAssert(
 | 
					 | 
				
			||||||
			subIndexIt != object->subIndexByName.end(),
 | 
					 | 
				
			||||||
			"Assembly object <" + _qualifiedName.str() + "> not found or does not contain code."
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
		object = dynamic_cast<Object const*>(object->subObjects[subIndexIt->second].get());
 | 
					 | 
				
			||||||
		yulAssert(object, "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code.");
 | 
					 | 
				
			||||||
		yulAssert(object->subId != std::numeric_limits<size_t>::max(), "");
 | 
					 | 
				
			||||||
		path.push_back({object->subId});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return path;
 | 
						return path;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shared_ptr<Object> Object::objectAt(shared_ptr<Object> const& _object, string const& _qualifiedName)
 | 
					std::shared_ptr<Object> Object::objectAt(std::shared_ptr<Object> const& _object, std::string const& _qualifiedName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (_qualifiedName.empty() || _qualifiedName == _object->name.str())
 | 
						std::shared_ptr<Object> object = nullptr;
 | 
				
			||||||
		return _object;
 | 
						traverseObjectTree(_object.get(), YulString(_qualifiedName), [&](Object const* _obj) -> bool {
 | 
				
			||||||
 | 
							if (_qualifiedName.empty() || _qualifiedName == _obj->name.str())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								object = std::make_shared<Object>(*_obj);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!boost::algorithm::starts_with(_qualifiedName, _object->name.str() + "."))
 | 
						return object;
 | 
				
			||||||
		return nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	string const subObjectPath = _qualifiedName.substr(_object->name.str().length() + 1);
 | 
					 | 
				
			||||||
	string const subObjectName = subObjectPath.substr(0, subObjectPath.find_first_of('.'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto subObjectIt = ranges::find_if(
 | 
					 | 
				
			||||||
		_object->subObjects,
 | 
					 | 
				
			||||||
		[&subObjectName](auto const& _subObject) { return _subObject->name.str() == subObjectName; }
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (subObjectIt == _object->subObjects.end())
 | 
					 | 
				
			||||||
		return nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto subObject = dynamic_pointer_cast<Object>(*subObjectIt);
 | 
					 | 
				
			||||||
	yulAssert(subObject, "Assembly object <" + subObject->name.str() + "> does not contain code.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return objectAt(subObject, subObjectPath);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -117,6 +117,14 @@ public:
 | 
				
			|||||||
	/// The path must not lead to a @a Data object (will throw in that case).
 | 
						/// The path must not lead to a @a Data object (will throw in that case).
 | 
				
			||||||
	std::vector<size_t> pathToSubObject(YulString _qualifiedName) const;
 | 
						std::vector<size_t> pathToSubObject(YulString _qualifiedName) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Traverses the @a _object tree applying the function @a _visitor at every subobject
 | 
				
			||||||
 | 
						/// in the path given by the @a _qualifiedName.
 | 
				
			||||||
 | 
						static void traverseObjectTree(
 | 
				
			||||||
 | 
							Object const* _object,
 | 
				
			||||||
 | 
							YulString _qualifiedName,
 | 
				
			||||||
 | 
							std::function<bool(Object const*)> _visitor
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// sub id for object if it is subobject of another object, max value if it is not subobject
 | 
						/// sub id for object if it is subobject of another object, max value if it is not subobject
 | 
				
			||||||
	size_t subId = std::numeric_limits<size_t>::max();
 | 
						size_t subId = std::numeric_limits<size_t>::max();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -130,7 +138,7 @@ public:
 | 
				
			|||||||
	/// @returns the name of the special metadata data object.
 | 
						/// @returns the name of the special metadata data object.
 | 
				
			||||||
	static std::string metadataName() { return ".metadata"; }
 | 
						static std::string metadataName() { return ".metadata"; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Recursively searches for an Object at @param _qualifiedName within @param _object.
 | 
						/// Searches for an Object at @param _qualifiedName within @param _object.
 | 
				
			||||||
	/// @returns a shared_ptr to the Object or a nullptr if it was not found.
 | 
						/// @returns a shared_ptr to the Object or a nullptr if it was not found.
 | 
				
			||||||
	static std::shared_ptr<Object> objectAt(
 | 
						static std::shared_ptr<Object> objectAt(
 | 
				
			||||||
		std::shared_ptr<Object> const& _object,
 | 
							std::shared_ptr<Object> const& _object,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user