#pragma once
#include <libyul/ASTForward.h>
#include <libyul/YulString.h>
#include <liblangutil/SourceLocation.h>
#include <memory>
#include <optional>
namespace solidity::yul
{
using Type = YulString;
struct DebugData
{
explicit DebugData(
langutil::SourceLocation _nativeLocation,
langutil::SourceLocation _originLocation = {},
std::optional<int64_t> _astID = {}
):
nativeLocation(std::move(_nativeLocation)),
originLocation(std::move(_originLocation)),
astID(std::move(_astID))
{}
static std::shared_ptr<DebugData const> create(
langutil::SourceLocation _nativeLocation = {},
langutil::SourceLocation _originLocation = {},
std::optional<int64_t> _astID = {}
)
{
return std::make_shared<DebugData const>(
std::move(_nativeLocation),
std::move(_originLocation),
std::move(_astID)
);
}
langutil::SourceLocation nativeLocation;
langutil::SourceLocation originLocation;
std::optional<int64_t> astID;
};
struct TypedName { std::shared_ptr<DebugData const> debugData; YulString name; Type type; };
using TypedNameList = std::vector<TypedName>;
enum class LiteralKind { Number, Boolean, String };
struct Literal { std::shared_ptr<DebugData const> debugData; LiteralKind kind; YulString value; Type type; };
struct Identifier { std::shared_ptr<DebugData const> debugData; YulString name; };
struct Assignment { std::shared_ptr<DebugData const> debugData; std::vector<Identifier> variableNames; std::unique_ptr<Expression> value; };
struct FunctionCall { std::shared_ptr<DebugData const> debugData; Identifier functionName; std::vector<Expression> arguments; };
struct ExpressionStatement { std::shared_ptr<DebugData const> debugData; Expression expression; };
struct VariableDeclaration { std::shared_ptr<DebugData const> debugData; TypedNameList variables; std::unique_ptr<Expression> value; };
struct Block { std::shared_ptr<DebugData const> debugData; std::vector<Statement> statements; };
struct FunctionDefinition { std::shared_ptr<DebugData const> debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; };
struct If { std::shared_ptr<DebugData const> debugData; std::unique_ptr<Expression> condition; Block body; };
struct Case { std::shared_ptr<DebugData const> debugData; std::unique_ptr<Literal> value; Block body; };
struct Switch { std::shared_ptr<DebugData const> debugData; std::unique_ptr<Expression> expression; std::vector<Case> cases; };
struct ForLoop { std::shared_ptr<DebugData const> debugData; Block pre; std::unique_ptr<Expression> condition; Block post; Block body; };
struct Break { std::shared_ptr<DebugData const> debugData; };
struct Continue { std::shared_ptr<DebugData const> debugData; };
struct Leave { std::shared_ptr<DebugData const> debugData; };
template <class T> inline langutil::SourceLocation nativeLocationOf(T const& _node)
{
return _node.debugData ? _node.debugData->nativeLocation : langutil::SourceLocation{};
}
template <class... Args> inline langutil::SourceLocation nativeLocationOf(std::variant<Args...> const& _node)
{
return std::visit([](auto const& _arg) { return nativeLocationOf(_arg); }, _node);
}
template <class T> inline langutil::SourceLocation originLocationOf(T const& _node)
{
return _node.debugData ? _node.debugData->originLocation : langutil::SourceLocation{};
}
template <class... Args> inline langutil::SourceLocation originLocationOf(std::variant<Args...> const& _node)
{
return std::visit([](auto const& _arg) { return originLocationOf(_arg); }, _node);
}
template <class T> inline std::shared_ptr<DebugData const> debugDataOf(T const& _node)
{
return _node.debugData;
}
template <class... Args> inline std::shared_ptr<DebugData const> debugDataOf(std::variant<Args...> const& _node)
{
return std::visit([](auto const& _arg) { return debugDataOf(_arg); }, _node);
}
inline bool hasDefaultCase(Switch const& _switch)
{
return std::any_of(
_switch.cases.begin(),
_switch.cases.end(),
[](Case const& _case) { return !_case.value; }
);
}
}