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
9c0f36db3b
commit
42c92cf342
@ -145,8 +145,36 @@ 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(), "");
|
||||||
|
|
||||||
|
vector<string> subObjectPathComponents;
|
||||||
|
boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of("."));
|
||||||
|
|
||||||
|
for (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 != numeric_limits<size_t>::max(), "");
|
||||||
|
if (_visitor(_object))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
|
vector<size_t> Object::pathToSubObject(YulString _qualifiedName) const
|
||||||
{
|
{
|
||||||
|
vector<size_t> path;
|
||||||
yulAssert(_qualifiedName != name, "");
|
yulAssert(_qualifiedName != name, "");
|
||||||
yulAssert(subIndexByName.count(name) == 0, "");
|
yulAssert(subIndexByName.count(name) == 0, "");
|
||||||
|
|
||||||
@ -154,49 +182,24 @@ 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(), "");
|
||||||
|
|
||||||
vector<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;
|
||||||
vector<size_t> path;
|
});
|
||||||
Object const* object = this;
|
|
||||||
for (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 != 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, 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 = 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