Skip to content

Commit 953871e

Browse files
authored
Merge pull request #6202 from diffblue/smt2_function_sort
SMT parser: function sorts -> and lambda terms
2 parents 9a04436 + 3804b18 commit 953871e

File tree

4 files changed

+70
-10
lines changed

4 files changed

+70
-10
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
lambda1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
(set-logic QF_BV)
2+
3+
(define-const min (-> (_ BitVec 8) (_ BitVec 8) (_ BitVec 8))
4+
(lambda ((a (_ BitVec 8)) (b (_ BitVec 8)))
5+
(ite (bvule a b) a b)))
6+
7+
(define-fun p1 () Bool (= (min #x01 #x02) #x01))
8+
(define-fun p2 () Bool (= (min #xff #xfe) #xfe))
9+
10+
; all must be true
11+
12+
(assert (not (and p1 p2)))
13+
14+
(check-sat)

src/solvers/smt2/smt2_parser.cpp

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ exprt smt2_parsert::let_expression()
215215
return let_exprt(variables, values, where);
216216
}
217217

218-
exprt smt2_parsert::quantifier_expression(irep_idt id)
218+
std::pair<binding_exprt::variablest, exprt> smt2_parsert::binding(irep_idt id)
219219
{
220220
if(next_token() != smt2_tokenizert::OPEN)
221221
throw error() << "expected bindings after " << id;
@@ -264,8 +264,6 @@ exprt smt2_parsert::quantifier_expression(irep_idt id)
264264
if(next_token() != smt2_tokenizert::CLOSE)
265265
throw error() << "expected ')' after " << id;
266266

267-
exprt result=expr;
268-
269267
// remove bindings from id_map
270268
for(const auto &b : bindings)
271269
id_map.erase(b.get_identifier());
@@ -274,14 +272,23 @@ exprt smt2_parsert::quantifier_expression(irep_idt id)
274272
for(auto &saved_id : saved_ids)
275273
id_map.insert(std::move(saved_id));
276274

277-
// go backwards, build quantified expression
278-
for(auto r_it=bindings.rbegin(); r_it!=bindings.rend(); r_it++)
279-
{
280-
quantifier_exprt quantifier(id, *r_it, result);
281-
result=quantifier;
282-
}
275+
return {std::move(bindings), std::move(expr)};
276+
}
283277

284-
return result;
278+
exprt smt2_parsert::lambda_expression()
279+
{
280+
auto binding = this->binding(ID_lambda);
281+
return lambda_exprt(binding.first, binding.second);
282+
}
283+
284+
exprt smt2_parsert::quantifier_expression(irep_idt id)
285+
{
286+
auto binding = this->binding(id);
287+
288+
if(binding.second.type().id() != ID_bool)
289+
throw error() << id << " expects a boolean term";
290+
291+
return quantifier_exprt(id, binding.first, binding.second);
285292
}
286293

287294
exprt smt2_parsert::function_application(
@@ -971,6 +978,7 @@ void smt2_parsert::setup_expressions()
971978
return from_integer(ieee_floatt::ROUND_TO_ZERO, unsignedbv_typet(32));
972979
};
973980

981+
expressions["lambda"] = [this] { return lambda_expression(); };
974982
expressions["let"] = [this] { return let_expression(); };
975983
expressions["exists"] = [this] { return quantifier_expression(ID_exists); };
976984
expressions["forall"] = [this] { return quantifier_expression(ID_forall); };
@@ -1236,6 +1244,32 @@ void smt2_parsert::setup_expressions()
12361244
expressions["fp.neg"] = [this] { return unary(ID_unary_minus, operands()); };
12371245
}
12381246

1247+
typet smt2_parsert::function_sort()
1248+
{
1249+
std::vector<typet> sorts;
1250+
1251+
// (-> sort+ sort)
1252+
// The last sort is the co-domain.
1253+
1254+
while(smt2_tokenizer.peek() != smt2_tokenizert::CLOSE)
1255+
{
1256+
if(smt2_tokenizer.peek() == smt2_tokenizert::END_OF_FILE)
1257+
throw error() << "unexpected end-of-file in a function sort";
1258+
1259+
sorts.push_back(sort()); // recursive call
1260+
}
1261+
1262+
next_token(); // eat the ')'
1263+
1264+
if(sorts.size() < 2)
1265+
throw error() << "expected function sort to have at least 2 type arguments";
1266+
1267+
auto codomain = std::move(sorts.back());
1268+
sorts.pop_back();
1269+
1270+
return mathematical_function_typet(std::move(sorts), std::move(codomain));
1271+
}
1272+
12391273
typet smt2_parsert::sort()
12401274
{
12411275
// a sort is one of the following three cases:
@@ -1334,6 +1368,8 @@ void smt2_parsert::setup_sorts()
13341368
else
13351369
throw error("unsupported array sort");
13361370
};
1371+
1372+
sorts["->"] = [this] { return function_sort(); };
13371373
}
13381374

13391375
smt2_parsert::signature_with_parameter_idst

src/solvers/smt2/smt2_parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ class smt2_parsert
163163
exprt binary(irep_idt, const exprt::operandst &);
164164
exprt unary(irep_idt, const exprt::operandst &);
165165

166+
std::pair<binding_exprt::variablest, exprt> binding(irep_idt);
167+
exprt lambda_expression();
166168
exprt let_expression();
167169
exprt quantifier_expression(irep_idt);
168170
exprt function_application(
@@ -177,6 +179,7 @@ class smt2_parsert
177179

178180
// sorts
179181
typet sort();
182+
typet function_sort();
180183
std::unordered_map<std::string, std::function<typet()>> sorts;
181184
void setup_sorts();
182185

0 commit comments

Comments
 (0)