aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/formal/SolverInterface.h
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/formal/SolverInterface.h')
-rw-r--r--libsolidity/formal/SolverInterface.h106
1 files changed, 83 insertions, 23 deletions
diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h
index df036190..cc8214de 100644
--- a/libsolidity/formal/SolverInterface.h
+++ b/libsolidity/formal/SolverInterface.h
@@ -45,7 +45,9 @@ enum class CheckResult
enum class Kind
{
Int,
- Bool
+ Bool,
+ Function,
+ Array
};
struct Sort
@@ -53,11 +55,46 @@ struct Sort
Sort(Kind _kind):
kind(_kind) {}
virtual ~Sort() = default;
- Kind const kind;
bool operator==(Sort const& _other) const { return kind == _other.kind; }
+
+ Kind const kind;
};
using SortPointer = std::shared_ptr<Sort>;
+struct FunctionSort: public Sort
+{
+ FunctionSort(std::vector<SortPointer> _domain, SortPointer _codomain):
+ Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {}
+ bool operator==(FunctionSort const& _other) const
+ {
+ if (!std::equal(
+ domain.begin(),
+ domain.end(),
+ _other.domain.begin(),
+ [&](SortPointer _a, SortPointer _b) { return *_a == *_b; }
+ ))
+ return false;
+ return Sort::operator==(_other) && *codomain == *_other.codomain;
+ }
+
+ std::vector<SortPointer> 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==(ArraySort const& _other) const
+ {
+ return Sort::operator==(_other) && *domain == *_other.domain && *range == *_other.range;
+ }
+
+ SortPointer domain;
+ SortPointer range;
+};
/// C++ representation of an SMTLIB2 expression.
class Expression
@@ -89,7 +126,9 @@ public:
{"+", 2},
{"-", 2},
{"*", 2},
- {"/", 2}
+ {"/", 2},
+ {"select", 2},
+ {"store", 3}
};
return operatorsArity.count(name) && operatorsArity.at(name) == arguments.size();
}
@@ -107,6 +146,36 @@ public:
return !std::move(_a) || std::move(_b);
}
+ /// select is the SMT representation of an array index access.
+ static Expression select(Expression _array, Expression _index)
+ {
+ solAssert(_array.sort->kind == Kind::Array, "");
+ auto const& arraySort = dynamic_cast<ArraySort const*>(_array.sort.get());
+ solAssert(arraySort, "");
+ solAssert(*arraySort->domain == *_index.sort, "");
+ return Expression(
+ "select",
+ std::vector<Expression>{std::move(_array), std::move(_index)},
+ arraySort->range
+ );
+ }
+
+ /// store is the SMT representation of an assignment to array index.
+ /// The function is pure and returns the modified array.
+ static Expression store(Expression _array, Expression _index, Expression _element)
+ {
+ solAssert(_array.sort->kind == Kind::Array, "");
+ auto const& arraySort = dynamic_cast<ArraySort const*>(_array.sort.get());
+ solAssert(arraySort, "");
+ solAssert(*arraySort->domain == *_index.sort, "");
+ solAssert(*arraySort->range == *_element.sort, "");
+ return Expression(
+ "store",
+ std::vector<Expression>{std::move(_array), std::move(_index), std::move(_element)},
+ _array.sort
+ );
+ }
+
friend Expression operator!(Expression _a)
{
return Expression("not", std::move(_a), Kind::Bool);
@@ -162,10 +231,12 @@ public:
Expression operator()(std::vector<Expression> _arguments) const
{
solAssert(
- arguments.empty(),
+ sort->kind == Kind::Function,
"Attempted function application to non-function."
);
- return Expression(name, std::move(_arguments), sort);
+ auto fSort = dynamic_cast<FunctionSort const*>(sort.get());
+ solAssert(fSort, "");
+ return Expression(name, std::move(_arguments), fSort->codomain);
}
std::string name;
@@ -198,26 +269,12 @@ public:
virtual void push() = 0;
virtual void pop() = 0;
- virtual void declareFunction(std::string _name, std::vector<SortPointer> const& _domain, Sort const& _codomain) = 0;
- Expression newFunction(std::string _name, std::vector<SortPointer> const& _domain, Sort const& _codomain)
+ virtual void declareVariable(std::string const& _name, Sort const& _sort) = 0;
+ Expression newVariable(std::string _name, SortPointer _sort)
{
- declareFunction(_name, _domain, _codomain);
// Subclasses should do something here
- return Expression(std::move(_name), {}, _codomain.kind);
- }
- virtual void declareInteger(std::string _name) = 0;
- Expression newInteger(std::string _name)
- {
- // Subclasses should do something here
- declareInteger(_name);
- return Expression(std::move(_name), {}, Kind::Int);
- }
- virtual void declareBool(std::string _name) = 0;
- Expression newBool(std::string _name)
- {
- // Subclasses should do something here
- declareBool(_name);
- return Expression(std::move(_name), {}, Kind::Bool);
+ declareVariable(_name, *_sort);
+ return Expression(std::move(_name), {}, std::move(_sort));
}
virtual void addAssertion(Expression const& _expr) = 0;
@@ -227,6 +284,9 @@ public:
virtual std::pair<CheckResult, std::vector<std::string>>
check(std::vector<Expression> const& _expressionsToEvaluate) = 0;
+ /// @returns a list of queries that the system was not able to respond to.
+ virtual std::vector<std::string> unhandledQueries() { return {}; }
+
protected:
// SMT query timeout in milliseconds.
static int const queryTimeout = 10000;