diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 247a90a5b..0ea9009fb 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -144,28 +144,29 @@ std::set Object::qualifiedDataNames() const return qualifiedNames; } -void Object::traverseObjectTree(Object const* _object, YulString _qualifiedName, std::function _visitor) +void Object::visitPath(YulString _qualifiedName, std::function _visitor) const { yulAssert(!_qualifiedName.empty(), ""); std::vector subObjectPathComponents; boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of(".")); + Object const* object = this; for (std::string const& currentSubObjectName: subObjectPathComponents) { yulAssert(!currentSubObjectName.empty(), ""); auto subObjectIt = ranges::find_if( - _object->subObjects, + object->subObjects, [¤tSubObjectName](auto const& _subObject) { return _subObject->name.str() == currentSubObjectName; } ); - if (subObjectIt != _object->subObjects.end()) + if (subObjectIt != object->subObjects.end()) { - _object = dynamic_cast(subObjectIt->get()); - yulAssert(_object, "Assembly object <" + _object->name.str() + "> not found or does not contain code."); - yulAssert(_object->subId != std::numeric_limits::max(), ""); - if (_visitor(_object)) + object = dynamic_cast(subObjectIt->get()); + yulAssert(object, "Assembly object <" + object->name.str() + "> not found or does not contain code."); + yulAssert(object->subId != std::numeric_limits::max(), ""); + if (_visitor(object)) break; } } @@ -181,7 +182,7 @@ std::vector Object::pathToSubObject(YulString _qualifiedName) const _qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)}; yulAssert(!_qualifiedName.empty(), ""); - traverseObjectTree(this, _qualifiedName, [&](Object const* _object) -> bool { + this->visitPath(_qualifiedName, [&](Object const* _object) -> bool { path.push_back({_object->subId}); return false; }); @@ -190,15 +191,15 @@ std::vector Object::pathToSubObject(YulString _qualifiedName) const std::shared_ptr Object::objectAt(std::shared_ptr const& _object, std::string const& _qualifiedName) { - std::shared_ptr object = nullptr; - traverseObjectTree(_object.get(), YulString(_qualifiedName), [&](Object const* _obj) -> bool { - if (_qualifiedName.empty() || _qualifiedName == _obj->name.str()) + std::shared_ptr foundObject = nullptr; + _object->visitPath(YulString(_qualifiedName), [&](Object const* _subObject) -> bool { + if (_qualifiedName.empty() || _qualifiedName == _subObject->name.str()) { - object = std::make_shared(*_obj); + foundObject = std::make_shared(*_subObject); return true; } return false; }); - return object; + return foundObject; } diff --git a/libyul/Object.h b/libyul/Object.h index d37d6c70b..37d802527 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -117,13 +117,14 @@ public: /// The path must not lead to a @a Data object (will throw in that case). std::vector 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, + /// Visits all subobjects in the path given by the @a _qualifiedName + /// of the current object applying the function @a _visitor. + /// If @a _visitor returns `true` the visiting stops, otherwise, + /// it continues until the last subobject in the path is reached. + void visitPath( YulString _qualifiedName, std::function _visitor - ); + ) const; /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max();