Skip to content

Commit 09a5ad9

Browse files
authored
Merge pull request #4672 from tautschnig/lambda-exprt
Add an API for lambda expressions [blocks: #4651]
2 parents 402d7a2 + 548e8e2 commit 09a5ad9

File tree

4 files changed

+89
-22
lines changed

4 files changed

+89
-22
lines changed

src/solvers/flattening/boolbv.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
294294
else if(expr.id()==ID_complex_imag)
295295
return convert_complex_imag(to_complex_imag_expr(expr));
296296
else if(expr.id()==ID_lambda)
297-
return convert_lambda(expr);
297+
return convert_lambda(to_lambda_expr(expr));
298298
else if(expr.id()==ID_array_of)
299299
return convert_array_of(to_array_of_expr(expr));
300300
else if(expr.id()==ID_let)
@@ -316,28 +316,21 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
316316
return conversion_failed(expr);
317317
}
318318

319-
bvt boolbvt::convert_lambda(const exprt &expr)
319+
bvt boolbvt::convert_lambda(const lambda_exprt &expr)
320320
{
321321
std::size_t width=boolbv_width(expr.type());
322322

323323
if(width==0)
324324
return conversion_failed(expr);
325325

326-
DATA_INVARIANT(
327-
expr.operands().size() == 2, "lambda expression should have two operands");
328-
329-
if(expr.type().id()!=ID_array)
330-
return conversion_failed(expr);
331-
332-
const exprt &array_size=
333-
to_array_type(expr.type()).size();
326+
const exprt &array_size = expr.type().size();
334327

335328
const auto size = numeric_cast<mp_integer>(array_size);
336329

337330
if(!size.has_value())
338331
return conversion_failed(expr);
339332

340-
typet counter_type=expr.op0().type();
333+
typet counter_type = expr.arg().type();
341334

342335
bvt bv;
343336
bv.resize(width);
@@ -346,10 +339,10 @@ bvt boolbvt::convert_lambda(const exprt &expr)
346339
{
347340
exprt counter=from_integer(i, counter_type);
348341

349-
exprt expr_op1(expr.op1());
350-
replace_expr(expr.op0(), counter, expr_op1);
342+
exprt body = expr.body();
343+
replace_expr(expr.arg(), counter, body);
351344

352-
const bvt &tmp=convert_bv(expr_op1);
345+
const bvt &tmp = convert_bv(body);
353346

354347
INVARIANT(
355348
*size * tmp.size() == width,

src/solvers/flattening/boolbv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Author: Daniel Kroening, [email protected]
2828

2929
class extractbit_exprt;
3030
class extractbits_exprt;
31+
class lambda_exprt;
3132
class member_exprt;
3233

3334
class boolbvt:public arrayst
@@ -148,7 +149,7 @@ class boolbvt:public arrayst
148149
virtual bvt convert_complex(const complex_exprt &expr);
149150
virtual bvt convert_complex_real(const complex_real_exprt &expr);
150151
virtual bvt convert_complex_imag(const complex_imag_exprt &expr);
151-
virtual bvt convert_lambda(const exprt &expr);
152+
virtual bvt convert_lambda(const lambda_exprt &expr);
152153
virtual bvt convert_let(const let_exprt &);
153154
virtual bvt convert_array_of(const array_of_exprt &expr);
154155
virtual bvt convert_union(const union_exprt &expr);

src/util/simplify_expr_array.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,14 @@ bool simplify_exprt::simplify_index(exprt &expr)
4848
{
4949
// simplify (lambda i: e)(x) to e[i/x]
5050

51-
const exprt &lambda_expr=array;
51+
const lambda_exprt &lambda_expr = to_lambda_expr(array);
5252

53-
if(lambda_expr.operands().size()!=2)
54-
return true;
55-
56-
if(expr.op1().type()==lambda_expr.op0().type())
53+
if(expr.op1().type() == lambda_expr.arg().type())
5754
{
58-
exprt tmp=lambda_expr.op1();
59-
replace_expr(lambda_expr.op0(), expr.op1(), tmp);
55+
exprt tmp = lambda_expr.body();
56+
replace_expr(lambda_expr.arg(), expr.op1(), tmp);
6057
expr.swap(tmp);
58+
simplify_rec(expr);
6159
return false;
6260
}
6361
}

src/util/std_expr.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4460,4 +4460,79 @@ inline cond_exprt &to_cond_expr(exprt &expr)
44604460
return ret;
44614461
}
44624462

4463+
/// \brief Expression to define a mapping from an argument (index) to elements.
4464+
/// This enables constructing an array via an anonymous function.
4465+
class lambda_exprt : public binary_exprt
4466+
{
4467+
public:
4468+
explicit lambda_exprt(symbol_exprt arg, exprt body, array_typet _type)
4469+
: binary_exprt(std::move(arg), ID_lambda, std::move(body), std::move(_type))
4470+
{
4471+
}
4472+
4473+
const array_typet &type() const
4474+
{
4475+
return static_cast<const array_typet &>(binary_exprt::type());
4476+
}
4477+
4478+
array_typet &type()
4479+
{
4480+
return static_cast<array_typet &>(binary_exprt::type());
4481+
}
4482+
4483+
const symbol_exprt &arg() const
4484+
{
4485+
return static_cast<const symbol_exprt &>(op0());
4486+
}
4487+
4488+
symbol_exprt &arg()
4489+
{
4490+
return static_cast<symbol_exprt &>(op0());
4491+
}
4492+
4493+
const exprt &body() const
4494+
{
4495+
return op1();
4496+
}
4497+
4498+
exprt &body()
4499+
{
4500+
return op1();
4501+
}
4502+
};
4503+
4504+
template <>
4505+
inline bool can_cast_expr<lambda_exprt>(const exprt &base)
4506+
{
4507+
return base.id() == ID_lambda;
4508+
}
4509+
4510+
inline void validate_expr(const lambda_exprt &value)
4511+
{
4512+
validate_operands(value, 2, "'Lambda' must have two operands");
4513+
}
4514+
4515+
/// \brief Cast an exprt to a \ref lambda_exprt
4516+
///
4517+
/// \a expr must be known to be \ref lambda_exprt.
4518+
///
4519+
/// \param expr: Source expression
4520+
/// \return Object of type \ref lambda_exprt
4521+
inline const lambda_exprt &to_lambda_expr(const exprt &expr)
4522+
{
4523+
PRECONDITION(expr.id() == ID_lambda);
4524+
const lambda_exprt &ret = static_cast<const lambda_exprt &>(expr);
4525+
validate_expr(ret);
4526+
return ret;
4527+
}
4528+
4529+
/// \copydoc to_lambda_expr(const exprt &)
4530+
inline lambda_exprt &to_lambda_expr(exprt &expr)
4531+
{
4532+
PRECONDITION(expr.id() == ID_lambda);
4533+
lambda_exprt &ret = static_cast<lambda_exprt &>(expr);
4534+
validate_expr(ret);
4535+
return ret;
4536+
}
4537+
44634538
#endif // CPROVER_UTIL_STD_EXPR_H

0 commit comments

Comments
 (0)