#pragma once
#include <libsolidity/ast/ASTVisitor.h>
#include <vector>
#include <set>
namespace solidity::frontend::smt
{
class VariableUsage: private ASTConstVisitor
{
public:
std::set<VariableDeclaration const*> touchedVariables(ASTNode const& _node, std::vector<CallableDeclaration const*> const& _outerCallstack);
void setFunctionInlining(std::function<bool(FunctionCall const&, ContractDefinition const*, ContractDefinition const*)> _inlineFunctionCalls) { m_inlineFunctionCalls = _inlineFunctionCalls; }
void setCurrentContract(ContractDefinition const& _contract) { m_currentContract = &_contract; }
private:
void endVisit(Identifier const& _node) override;
void endVisit(IndexAccess const& _node) override;
void endVisit(FunctionCall const& _node) override;
bool visit(FunctionDefinition const& _node) override;
void endVisit(FunctionDefinition const& _node) override;
void endVisit(ModifierInvocation const& _node) override;
void endVisit(PlaceholderStatement const& _node) override;
void checkIdentifier(Identifier const& _identifier);
ContractDefinition const* currentScopeContract();
std::set<VariableDeclaration const*> m_touchedVariables;
std::vector<CallableDeclaration const*> m_callStack;
CallableDeclaration const* m_lastCall = nullptr;
ContractDefinition const* m_currentContract = nullptr;
std::function<bool(FunctionCall const&, ContractDefinition const*, ContractDefinition const*)> m_inlineFunctionCalls = [](FunctionCall const&, ContractDefinition const*, ContractDefinition const*) { return false; };
};
}