Skip to content

Commit 36c1fa5

Browse files
author
Daniel Kroening
authored
Merge pull request #3503 from diffblue/smt2-get-assignment
SMT2: get-assignment
2 parents 13aef19 + 4c6a340 commit 36c1fa5

File tree

7 files changed

+101
-2
lines changed

7 files changed

+101
-2
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
get-assignment1.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^sat$
7+
^\(\(y_equality true\)\)$
8+
--
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(set-logic QF_BV)
2+
(set-option :produce-assignments true)
3+
4+
(declare-const var_x (_ BitVec 8)) ; nullary function
5+
(declare-const var_y (_ BitVec 8)) ; nullary function
6+
(declare-const var_z (_ BitVec 8)) ; nullary function
7+
8+
(assert (= var_x #x01))
9+
(assert (! (= var_y #x02) :named y_equality))
10+
(assert (= var_z (bvadd var_x var_y)))
11+
12+
(check-sat)
13+
(get-assignment)

src/solvers/smt2/smt2_parser.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,39 @@ exprt smt2_parsert::function_application()
427427
throw error(msg.str());
428428
}
429429
}
430+
else if(buffer == "!")
431+
{
432+
// these are "term attributes"
433+
const auto term = expression();
434+
435+
while(peek() == KEYWORD)
436+
{
437+
next_token(); // eat the keyword
438+
if(buffer == "named")
439+
{
440+
// 'named terms' must be Boolean
441+
if(term.type().id() != ID_bool)
442+
throw error("named terms must be Boolean");
443+
444+
if(next_token() == SYMBOL)
445+
{
446+
const symbol_exprt symbol_expr(buffer, bool_typet());
447+
auto &named_term = named_terms[symbol_expr.get_identifier()];
448+
named_term.term = term;
449+
named_term.name = symbol_expr;
450+
}
451+
else
452+
throw error("invalid name attribute, expected symbol");
453+
}
454+
else
455+
throw error("unknown term attribute");
456+
}
457+
458+
if(next_token() != CLOSE)
459+
throw error("expected ')' at end of term attribute");
460+
else
461+
return term;
462+
}
430463
else
431464
{
432465
// non-indexed symbol; hash it

src/solvers/smt2/smt2_parser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ class smt2_parsert:public smt2_tokenizert
4242
using id_mapt=std::map<irep_idt, idt>;
4343
id_mapt id_map;
4444

45+
struct named_termt
46+
{
47+
exprt term;
48+
symbol_exprt name;
49+
};
50+
51+
using named_termst = std::map<irep_idt, named_termt>;
52+
named_termst named_terms;
53+
4554
bool exit;
4655

4756
/// This skips tokens until all bracketed expressions are closed

src/solvers/smt2/smt2_solver.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,36 @@ void smt2_solvert::command(const std::string &c)
232232

233233
std::cout << smt2_format(constant_exprt(buffer, string_typet())) << '\n';
234234
}
235+
else if(c == "get-assignment")
236+
{
237+
// print satisfying assignment for all named expressions
238+
239+
if(status != SAT)
240+
throw error("model is not available");
241+
242+
bool first = true;
243+
244+
std::cout << '(';
245+
for(const auto &named_term : named_terms)
246+
{
247+
const symbol_tablet symbol_table;
248+
const namespacet ns(symbol_table);
249+
const auto value =
250+
simplify_expr(solver.get(named_term.second.term), ns);
251+
252+
if(value.is_constant())
253+
{
254+
if(first)
255+
first = false;
256+
else
257+
std::cout << '\n' << ' ';
258+
259+
std::cout << '(' << smt2_format(named_term.second.name) << ' '
260+
<< smt2_format(value) << ')';
261+
}
262+
}
263+
std::cout << ')' << '\n';
264+
}
235265
else if(c == "simplify")
236266
{
237267
// this is a command that Z3 appears to implement
@@ -256,7 +286,6 @@ void smt2_solvert::command(const std::string &c)
256286
| ( define-funs-rec ( hfunction_deci n+1 ) ( htermi n+1 ) )
257287
| ( define-sort hsymboli ( hsymboli ??? ) hsorti )
258288
| ( get-assertions )
259-
| ( get-assignment )
260289
| ( get-info hinfo_flag i )
261290
| ( get-model )
262291
| ( get-option hkeywordi )

src/solvers/smt2/smt2_tokenizer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,13 @@ void smt2_tokenizert::get_token_from_stream()
254254

255255
case ':': // keyword
256256
token = get_simple_symbol();
257-
return;
257+
if(token == SYMBOL)
258+
{
259+
token = KEYWORD;
260+
return;
261+
}
262+
else
263+
throw error("expecting symbol after colon");
258264

259265
case '#':
260266
if(in->get(ch))

src/solvers/smt2/smt2_tokenizer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class smt2_tokenizert:public parsert
6060
STRING_LITERAL,
6161
NUMERAL,
6262
SYMBOL,
63+
KEYWORD,
6364
OPEN,
6465
CLOSE
6566
};

0 commit comments

Comments
 (0)