Skip to content

SMT parser: function sorts -> and lambda terms #6202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions regression/smt2_solver/function-applications/lambda1.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE
lambda1.smt2

^EXIT=0$
^SIGNAL=0$
^unsat$
--
14 changes: 14 additions & 0 deletions regression/smt2_solver/function-applications/lambda1.smt2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(set-logic QF_BV)

(define-const min (-> (_ BitVec 8) (_ BitVec 8) (_ BitVec 8))
(lambda ((a (_ BitVec 8)) (b (_ BitVec 8)))
(ite (bvule a b) a b)))

(define-fun p1 () Bool (= (min #x01 #x02) #x01))
(define-fun p2 () Bool (= (min #xff #xfe) #xfe))

; all must be true

(assert (not (and p1 p2)))

(check-sat)
56 changes: 46 additions & 10 deletions src/solvers/smt2/smt2_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ exprt smt2_parsert::let_expression()
return let_exprt(variables, values, where);
}

exprt smt2_parsert::quantifier_expression(irep_idt id)
std::pair<binding_exprt::variablest, exprt> smt2_parsert::binding(irep_idt id)
{
if(next_token() != smt2_tokenizert::OPEN)
throw error() << "expected bindings after " << id;
Expand Down Expand Up @@ -264,8 +264,6 @@ exprt smt2_parsert::quantifier_expression(irep_idt id)
if(next_token() != smt2_tokenizert::CLOSE)
throw error() << "expected ')' after " << id;

exprt result=expr;

// remove bindings from id_map
for(const auto &b : bindings)
id_map.erase(b.get_identifier());
Expand All @@ -274,14 +272,23 @@ exprt smt2_parsert::quantifier_expression(irep_idt id)
for(auto &saved_id : saved_ids)
id_map.insert(std::move(saved_id));

// go backwards, build quantified expression
for(auto r_it=bindings.rbegin(); r_it!=bindings.rend(); r_it++)
{
quantifier_exprt quantifier(id, *r_it, result);
result=quantifier;
}
return {std::move(bindings), std::move(expr)};
}

return result;
exprt smt2_parsert::lambda_expression()
{
auto binding = this->binding(ID_lambda);
return lambda_exprt(binding.first, binding.second);
}

exprt smt2_parsert::quantifier_expression(irep_idt id)
{
auto binding = this->binding(id);

if(binding.second.type().id() != ID_bool)
throw error() << id << " expects a boolean term";

return quantifier_exprt(id, binding.first, binding.second);
}

exprt smt2_parsert::function_application(
Expand Down Expand Up @@ -971,6 +978,7 @@ void smt2_parsert::setup_expressions()
return from_integer(ieee_floatt::ROUND_TO_ZERO, unsignedbv_typet(32));
};

expressions["lambda"] = [this] { return lambda_expression(); };
expressions["let"] = [this] { return let_expression(); };
expressions["exists"] = [this] { return quantifier_expression(ID_exists); };
expressions["forall"] = [this] { return quantifier_expression(ID_forall); };
Expand Down Expand Up @@ -1236,6 +1244,32 @@ void smt2_parsert::setup_expressions()
expressions["fp.neg"] = [this] { return unary(ID_unary_minus, operands()); };
}

typet smt2_parsert::function_sort()
{
std::vector<typet> sorts;

// (-> sort+ sort)
// The last sort is the co-domain.

while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
{
if(smt2_tokenizer.peek() == smt2_tokenizert::END_OF_FILE)
throw error() << "unexpected end-of-file in a function sort";

sorts.push_back(sort()); // recursive call
}

next_token(); // eat the ')'

if(sorts.size() < 2)
throw error() << "expected function sort to have at least 2 type arguments";

auto codomain = std::move(sorts.back());
sorts.pop_back();

return mathematical_function_typet(std::move(sorts), std::move(codomain));
}

typet smt2_parsert::sort()
{
// a sort is one of the following three cases:
Expand Down Expand Up @@ -1334,6 +1368,8 @@ void smt2_parsert::setup_sorts()
else
throw error("unsupported array sort");
};

sorts["->"] = [this] { return function_sort(); };
}

smt2_parsert::signature_with_parameter_idst
Expand Down
3 changes: 3 additions & 0 deletions src/solvers/smt2/smt2_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class smt2_parsert
exprt binary(irep_idt, const exprt::operandst &);
exprt unary(irep_idt, const exprt::operandst &);

std::pair<binding_exprt::variablest, exprt> binding(irep_idt);
exprt lambda_expression();
exprt let_expression();
exprt quantifier_expression(irep_idt);
exprt function_application(
Expand All @@ -177,6 +179,7 @@ class smt2_parsert

// sorts
typet sort();
typet function_sort();
std::unordered_map<std::string, std::function<typet()>> sorts;
void setup_sorts();

Expand Down