/*
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 .
*/
#pragma once
#include
#include
#include
namespace solidity::yul
{
/**
* Class that implements a reverse lookup for an ``unordered_map>`` by wrapping the
* two such maps - one ordered, and one reversed, e.g.
*
* m_ordered m_reversed
* f -> (g,) g -> (f,)
* c -> (b,d,e,) d -> (c,)
* a -> (b,c,) c -> (a,)
* e -> (c,)
* b -> (a,c,)
*
* The above example will from here onwards be referenced as ```Ref 1```.
*
* This allows us to have simultaneously managed insertion and deletion via a single interface, instead of manually
* managing this at the point of usage (see ``DataFlowAnalyzer``).
*/
class VariableAssignmentMap
{
public:
VariableAssignmentMap() = default;
/**
* Insert a set of values for the provided key ``_variable`` into ``m_ordered`` and ``m_reversed``.
* This method will erase all references of ``_variable`` from both sets before performing the insertion,
* akin to container assignment with subscript operator, i.e. container[index] = value.
* For example, if ``_variable`` is ``x`` and ``_references`` is ``{"y", "z"}``, the following would be added to ``Ref 1``:
*
* m_ordered m_reversed
* x -> (y, z,) y -> (x,)
* y -> (z,)
*
* @param _variable current expression variable
* @param _references all referenced variables in the expression assigned to ``_variable``
*/
void set(YulString const& _variable, std::set const& _references);
/**
* Erase entries in both maps based on provided ``_variable``. The behaviour is the same as ``set("x", {})``.
* For example, after deleting ``c`` for ``Ref 1``, ``Ref 1`` would contain the following:
*
* m_ordered m_reversed
* f -> (g,) g -> (f,)
* a -> (b,c,) c -> (a,)
* b -> (a,)
*
* @param _variable variable to erase
*/
void erase(YulString const& _variable);
std::set const* getOrderedOrNullptr(YulString const& _variable) const;
std::set const* getReversedOrNullptr(YulString const& _variable) const;
private:
/// m_ordered[a].contains[b] <=> the current expression assigned to ``a`` references ``b``
std::unordered_map> m_ordered;
/// m_reversed[b].contains[a] <=> the current expression assigned to ``a`` references ``b``
std::unordered_map> m_reversed;
};
} // solidity::yul