Skip to content

Commit f13b9d7

Browse files
author
Daniel Kroening
committed
quantifiers are variable bindings
This commit makes the quantifier base class use the bindings base class. Methods and constructor for the special case of quantifying over one variable are retained.
1 parent 797033f commit f13b9d7

File tree

4 files changed

+40
-34
lines changed

4 files changed

+40
-34
lines changed

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,12 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
292292
else if(expr.id()==ID_forall ||
293293
expr.id()==ID_exists)
294294
{
295-
// op0 is a declaration,
296-
// op1 the bound expression
295+
// op0 is a tuple with one declaration,
296+
// op1 is the bound expression
297297
assert(expr.operands().size()==2);
298298
expr.type()=bool_typet();
299299

300-
if(expr.op0().get(ID_statement)!=ID_decl)
300+
if(expr.op0().op0().get(ID_statement) != ID_decl)
301301
{
302302
error().source_location = expr.source_location();
303303
error() << "expected declaration as operand of quantifier" << eom;
@@ -311,9 +311,8 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
311311
throw 0;
312312
}
313313

314-
// replace declaration by symbol expression
315-
symbol_exprt bound=to_symbol_expr(expr.op0().op0());
316-
expr.op0().swap(bound);
314+
// replace declarations by symbol expressions
315+
expr.op0().op0() = to_symbol_expr(expr.op0().op0().op0());
317316

318317
implicit_typecast_bool(expr.op1());
319318
}
@@ -739,9 +738,9 @@ void c_typecheck_baset::typecheck_expr_operands(exprt &expr)
739738
else if(expr.id()==ID_forall || expr.id()==ID_exists)
740739
{
741740
assert(expr.operands().size()==2);
741+
assert(expr.op0().operands().size() == 1);
742742

743-
ansi_c_declarationt &declaration=
744-
to_ansi_c_declaration(expr.op0());
743+
ansi_c_declarationt &declaration = to_ansi_c_declaration(expr.op0().op0());
745744

746745
typecheck_declaration(declaration);
747746

@@ -780,7 +779,7 @@ void c_typecheck_baset::typecheck_expr_operands(exprt &expr)
780779
code_declt decl(symbol.symbol_expr());
781780
decl.add_source_location()=declaration.source_location();
782781

783-
expr.op0()=decl;
782+
expr.op0().op0() = decl;
784783

785784
typecheck_expr(expr.op1());
786785
}

src/ansi-c/expr2c.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,13 +798,17 @@ std::string expr2ct::convert_quantifier(
798798
if(src.operands().size()!=2)
799799
return convert_norep(src, precedence);
800800

801+
// our made-up syntax can only do one symbol
802+
if(src.op0().operands().size() != 1)
803+
return convert_norep(src, precedence);
804+
801805
unsigned p0, p1;
802806

803-
std::string op0=convert_with_precedence(src.op0(), p0);
807+
std::string op0 = convert_with_precedence(src.op0().op0(), p0);
804808
std::string op1=convert_with_precedence(src.op1(), p1);
805809

806810
std::string dest=symbol+" { ";
807-
dest+=convert(src.op0().type());
811+
dest += convert(src.op0().op0().type());
808812
dest+=" "+op0+"; ";
809813
dest+=op1;
810814
dest+=" }";

src/ansi-c/parser.y

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ extern char *yyansi_ctext;
2626

2727
#include "ansi_c_y.tab.h"
2828

29+
#include <util/mathematical_expr.h>
30+
2931
#ifdef _MSC_VER
3032
// possible loss of data
3133
#pragma warning(disable:4242)
@@ -468,7 +470,7 @@ quantifier_expression:
468470
{
469471
$$=$1;
470472
set($$, ID_forall);
471-
mto($$, $4);
473+
parser_stack($$).add_to_operands(tuple_exprt( { std::move(parser_stack($4)) } ));
472474
mto($$, $5);
473475
PARSER.pop_scope();
474476
}
@@ -478,15 +480,15 @@ quantifier_expression:
478480
// to bind only very weakly.
479481
$$=$1;
480482
set($$, ID_forall);
481-
mto($$, $3);
483+
parser_stack($$).add_to_operands(tuple_exprt( { std::move(parser_stack($3)) } ));
482484
mto($$, $4);
483485
PARSER.pop_scope();
484486
}
485487
| TOK_EXISTS compound_scope '{' declaration comma_expression '}'
486488
{
487489
$$=$1;
488490
set($$, ID_exists);
489-
mto($$, $4);
491+
parser_stack($$).add_to_operands(tuple_exprt( { std::move(parser_stack($4)) } ));
490492
mto($$, $5);
491493
PARSER.pop_scope();
492494
}
@@ -496,7 +498,7 @@ quantifier_expression:
496498
// to bind only very weakly.
497499
$$=$1;
498500
set($$, ID_exists);
499-
mto($$, $3);
501+
parser_stack($$).add_to_operands(tuple_exprt( { std::move(parser_stack($3)) } ));
500502
mto($$, $4);
501503
PARSER.pop_scope();
502504
}

src/util/mathematical_expr.h

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -315,35 +315,35 @@ class binding_exprt : public binary_exprt
315315
};
316316

317317
/// \brief A base class for quantifier expressions
318-
class quantifier_exprt : public binary_predicate_exprt
318+
class quantifier_exprt : public binding_exprt
319319
{
320320
public:
321-
quantifier_exprt(
322-
const irep_idt &_id,
323-
const symbol_exprt &_symbol,
324-
const exprt &_where)
325-
: binary_predicate_exprt(_symbol, _id, _where)
321+
/// constructor for single variable
322+
quantifier_exprt(irep_idt _id, symbol_exprt _symbol, exprt _where)
323+
: binding_exprt(_id, {std::move(_symbol)}, std::move(_where), bool_typet())
326324
{
327325
}
328326

329-
symbol_exprt &symbol()
330-
{
331-
return static_cast<symbol_exprt &>(op0());
332-
}
333-
334-
const symbol_exprt &symbol() const
327+
/// constructor for multiple variables
328+
quantifier_exprt(irep_idt _id, const variablest &_variables, exprt _where)
329+
: binding_exprt(_id, _variables, std::move(_where), bool_typet())
335330
{
336-
return static_cast<const symbol_exprt &>(op0());
337331
}
338332

339-
exprt &where()
333+
// for the special case of one variable
334+
symbol_exprt &symbol()
340335
{
341-
return op1();
336+
auto &variables = this->variables();
337+
PRECONDITION(variables.size() == 1);
338+
return variables.front();
342339
}
343340

344-
const exprt &where() const
341+
// for the special case of one variable
342+
const symbol_exprt &symbol() const
345343
{
346-
return op1();
344+
auto &variables = this->variables();
345+
PRECONDITION(variables.size() == 1);
346+
return variables.front();
347347
}
348348
};
349349

@@ -356,8 +356,9 @@ inline bool can_cast_expr<quantifier_exprt>(const exprt &base)
356356
inline void validate_expr(const quantifier_exprt &value)
357357
{
358358
validate_operands(value, 2, "quantifier expressions must have two operands");
359-
DATA_INVARIANT(
360-
value.op0().id() == ID_symbol, "quantified variable shall be a symbol");
359+
for(auto &op : value.variables())
360+
DATA_INVARIANT(
361+
op.id() == ID_symbol, "quantified variable shall be a symbol");
361362
}
362363

363364
/// \brief Cast an exprt to a \ref quantifier_exprt

0 commit comments

Comments
 (0)