@@ -4283,47 +4283,109 @@ class infinity_exprt : public nullary_exprt
4283
4283
};
4284
4284
4285
4285
// / \brief A let expression
4286
- class let_exprt : public ternary_exprt
4286
+ class let_exprt : public binary_exprt
4287
4287
{
4288
4288
public:
4289
- let_exprt (symbol_exprt symbol, exprt value, const exprt &where)
4290
- : ternary_exprt(
4289
+ class let_binding_exprt : public binary_exprt
4290
+ {
4291
+ public:
4292
+ let_binding_exprt (symbol_exprt symbol, exprt value)
4293
+ : binary_exprt(
4294
+ std::move (symbol),
4295
+ ID_let,
4296
+ std::move(value),
4297
+ typet(ID_tuple))
4298
+ {
4299
+ }
4300
+
4301
+ const symbol_exprt &symbol () const
4302
+ {
4303
+ return static_cast <const symbol_exprt &>(op0 ());
4304
+ }
4305
+
4306
+ symbol_exprt &symbol ()
4307
+ {
4308
+ return static_cast <symbol_exprt &>(op0 ());
4309
+ }
4310
+
4311
+ const exprt &value () const
4312
+ {
4313
+ return op1 ();
4314
+ }
4315
+
4316
+ exprt &value ()
4317
+ {
4318
+ return op1 ();
4319
+ }
4320
+ };
4321
+
4322
+ using bindingst = std::vector<let_binding_exprt>;
4323
+
4324
+ let_exprt (const bindingst &bindings, const exprt &where)
4325
+ : binary_exprt(
4326
+ multi_ary_exprt (ID_tuple, (const operandst &)bindings, typet(ID_tuple)),
4291
4327
ID_let,
4292
- std::move (symbol),
4293
- std::move(value),
4294
4328
where,
4295
4329
where.type())
4296
4330
{
4297
4331
}
4298
4332
4333
+ // / convenience constructor for the case of a single binding
4334
+ let_exprt (symbol_exprt symbol, exprt value, const exprt &where)
4335
+ : let_exprt({ let_binding_exprt (std::move (symbol), std::move (value)) }, where)
4336
+ {
4337
+ }
4338
+
4339
+ bindingst &bindings ()
4340
+ {
4341
+ return (bindingst &)op0 ().operands ();
4342
+ }
4343
+
4344
+ const bindingst &bindings () const
4345
+ {
4346
+ return (bindingst &)op0 ().operands ();
4347
+ }
4348
+
4349
+ // / convenience accessor for the symbol of a single binding
4299
4350
symbol_exprt &symbol ()
4300
4351
{
4301
- return static_cast <symbol_exprt &>(op0 ());
4352
+ auto &bindings = this ->bindings ();
4353
+ PRECONDITION (bindings.size () == 1 );
4354
+ return bindings.front ().symbol ();
4302
4355
}
4303
4356
4357
+ // / convenience accessor for the symbol of a single binding
4304
4358
const symbol_exprt &symbol () const
4305
4359
{
4306
- return static_cast <const symbol_exprt &>(op0 ());
4360
+ const auto &bindings = this ->bindings ();
4361
+ PRECONDITION (bindings.size () == 1 );
4362
+ return bindings.front ().symbol ();
4307
4363
}
4308
4364
4365
+ // / convenience accessor for the value of a single binding
4309
4366
exprt &value ()
4310
4367
{
4311
- return op1 ();
4368
+ auto &bindings = this ->bindings ();
4369
+ PRECONDITION (bindings.size () == 1 );
4370
+ return bindings.front ().value ();
4312
4371
}
4313
4372
4373
+ // / convenience accessor for the value of a single binding
4314
4374
const exprt &value () const
4315
4375
{
4316
- return op1 ();
4376
+ const auto &bindings = this ->bindings ();
4377
+ PRECONDITION (bindings.size () == 1 );
4378
+ return bindings.front ().value ();
4317
4379
}
4318
4380
4319
4381
exprt &where ()
4320
4382
{
4321
- return op2 ();
4383
+ return op1 ();
4322
4384
}
4323
4385
4324
4386
const exprt &where () const
4325
4387
{
4326
- return op2 ();
4388
+ return op1 ();
4327
4389
}
4328
4390
};
4329
4391
@@ -4335,7 +4397,22 @@ inline bool can_cast_expr<let_exprt>(const exprt &base)
4335
4397
4336
4398
inline void validate_expr (const let_exprt &value)
4337
4399
{
4338
- validate_operands (value, 3 , " Let must have three operands" );
4400
+ validate_operands (value, 2 , " Let must have two operands" );
4401
+
4402
+ // symbols and assignments alternate
4403
+ for (const auto &binding : value.bindings ())
4404
+ {
4405
+ DATA_INVARIANT (
4406
+ binding.id () == ID_let_binding, " let bindings must have correct id" );
4407
+
4408
+ DATA_INVARIANT (
4409
+ binding.symbol ().id () == ID_symbol,
4410
+ " let binding symbols must be symbols" );
4411
+
4412
+ DATA_INVARIANT (
4413
+ binding.symbol ().type () == binding.value ().type (),
4414
+ " let bindings must be type consistent" );
4415
+ }
4339
4416
}
4340
4417
4341
4418
// / \brief Cast an exprt to a \ref let_exprt
0 commit comments