/*
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 .
*/
// SPDX-License-Identifier: GPL-3.0
#pragma once
#include
#include
#include
#include
namespace solidity::smtutil
{
enum class Kind
{
Int,
Bool,
BitVector,
Function,
Array,
Sort,
Tuple
};
struct Sort
{
Sort(Kind _kind):
kind(_kind) {}
virtual ~Sort() = default;
virtual bool operator==(Sort const& _other) const { return kind == _other.kind; }
Kind const kind;
};
using SortPointer = std::shared_ptr;
struct IntSort: public Sort
{
IntSort(bool _signed):
Sort(Kind::Int),
isSigned(_signed)
{}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto otherIntSort = dynamic_cast(&_other);
smtAssert(otherIntSort);
return isSigned == otherIntSort->isSigned;
}
bool isSigned;
};
struct BitVectorSort: public Sort
{
BitVectorSort(unsigned _size):
Sort(Kind::BitVector),
size(_size)
{}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto otherBitVectorSort = dynamic_cast(&_other);
smtAssert(otherBitVectorSort);
return size == otherBitVectorSort->size;
}
unsigned size;
};
struct FunctionSort: public Sort
{
FunctionSort(std::vector _domain, SortPointer _codomain):
Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto _otherFunction = dynamic_cast(&_other);
smtAssert(_otherFunction, "");
if (domain.size() != _otherFunction->domain.size())
return false;
if (!std::equal(
domain.begin(),
domain.end(),
_otherFunction->domain.begin(),
[&](SortPointer _a, SortPointer _b) { return *_a == *_b; }
))
return false;
smtAssert(codomain, "");
smtAssert(_otherFunction->codomain, "");
return *codomain == *_otherFunction->codomain;
}
std::vector domain;
SortPointer codomain;
};
struct ArraySort: public Sort
{
/// _domain is the sort of the indices
/// _range is the sort of the values
ArraySort(SortPointer _domain, SortPointer _range):
Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto _otherArray = dynamic_cast(&_other);
smtAssert(_otherArray, "");
smtAssert(_otherArray->domain, "");
smtAssert(_otherArray->range, "");
smtAssert(domain, "");
smtAssert(range, "");
return *domain == *_otherArray->domain && *range == *_otherArray->range;
}
SortPointer domain;
SortPointer range;
};
struct SortSort: public Sort
{
SortSort(SortPointer _inner): Sort(Kind::Sort), inner(std::move(_inner)) {}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto _otherSort = dynamic_cast(&_other);
smtAssert(_otherSort, "");
smtAssert(_otherSort->inner, "");
smtAssert(inner, "");
return *inner == *_otherSort->inner;
}
SortPointer inner;
};
struct TupleSort: public Sort
{
TupleSort(
std::string _name,
std::vector _members,
std::vector _components
):
Sort(Kind::Tuple),
name(std::move(_name)),
members(std::move(_members)),
components(std::move(_components))
{
for (size_t i = 0; i < members.size(); ++i)
memberToIndex[members.at(i)] = i;
}
SortPointer memberSort(std::string const& _member)
{
return components.at(memberToIndex.at(_member));
}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto _otherTuple = dynamic_cast(&_other);
smtAssert(_otherTuple, "");
if (name != _otherTuple->name)
return false;
if (members != _otherTuple->members)
return false;
if (components.size() != _otherTuple->components.size())
return false;
if (!std::equal(
components.begin(),
components.end(),
_otherTuple->components.begin(),
[&](SortPointer _a, SortPointer _b) { return *_a == *_b; }
))
return false;
return true;
}
std::string const name;
std::vector const members;
std::vector const components;
std::map memberToIndex;
};
/** Frequently used sorts.*/
struct SortProvider
{
static std::shared_ptr const boolSort;
static std::shared_ptr const uintSort;
static std::shared_ptr const sintSort;
static std::shared_ptr intSort(bool _signed = false);
static std::shared_ptr const bitVectorSort;
};
}