@@ -1001,7 +1001,35 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
1001
1001
}
1002
1002
else if (expr.id () == ID_smv_setin)
1003
1003
{
1004
- expr.type ()=bool_typet ();
1004
+ auto &lhs = to_binary_expr (expr).lhs ();
1005
+ auto &rhs = to_binary_expr (expr).rhs ();
1006
+
1007
+ typecheck_expr_rec (lhs, mode);
1008
+ typecheck_expr_rec (rhs, mode);
1009
+
1010
+ // The RHS can be a set or a singleton
1011
+ if (rhs.type ().id () == ID_smv_set)
1012
+ {
1013
+ PRECONDITION (rhs.id () == ID_smv_set);
1014
+ // do type union
1015
+ typet op_type = lhs.type ();
1016
+ for (auto &op : rhs.operands ())
1017
+ op_type = type_union (op_type, op.type (), expr.source_location ());
1018
+ // now convert
1019
+ convert_expr_to (lhs, op_type);
1020
+ for (auto &op : rhs.operands ())
1021
+ convert_expr_to (op, op_type);
1022
+ }
1023
+ else
1024
+ {
1025
+ typet op_type =
1026
+ type_union (lhs.type (), rhs.type (), expr.source_location ());
1027
+
1028
+ convert_expr_to (lhs, op_type);
1029
+ convert_expr_to (rhs, op_type);
1030
+ }
1031
+
1032
+ expr.type () = bool_typet ();
1005
1033
}
1006
1034
else if (expr.id () == ID_smv_setnotin)
1007
1035
{
@@ -1232,6 +1260,14 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
1232
1260
<< " signed operand must have unsigned word type" ;
1233
1261
}
1234
1262
}
1263
+ else if (expr.id () == ID_smv_set)
1264
+ {
1265
+ // a set literal
1266
+ expr.type () = typet{ID_smv_set};
1267
+
1268
+ for (auto &op : expr.operands ())
1269
+ typecheck_expr_rec (op, mode);
1270
+ }
1235
1271
else
1236
1272
{
1237
1273
throw errort ().with_location (expr.find_source_location ())
@@ -1271,6 +1307,33 @@ void smv_typecheckt::lower_node(exprt &expr) const
1271
1307
{
1272
1308
expr = typecast_exprt{to_smv_unsigned_cast_expr (expr).op (), expr.type ()};
1273
1309
}
1310
+ else if (expr.id () == ID_smv_setin)
1311
+ {
1312
+ auto &lhs = to_binary_expr (expr).lhs ();
1313
+ auto &rhs = to_binary_expr (expr).rhs ();
1314
+ if (rhs.type ().id () == ID_smv_set)
1315
+ {
1316
+ DATA_INVARIANT (
1317
+ rhs.id () == ID_smv_set, " rhs of in must be set expression" );
1318
+ // this is an 'or'
1319
+ exprt::operandst disjuncts;
1320
+ disjuncts.reserve (rhs.operands ().size ());
1321
+ for (auto &op : rhs.operands ())
1322
+ {
1323
+ DATA_INVARIANT (
1324
+ lhs.type () == op.type (), " lhs/rhs of in must have same type" );
1325
+ disjuncts.push_back (equal_exprt{lhs, op});
1326
+ }
1327
+ expr = disjunction (std::move (disjuncts));
1328
+ }
1329
+ else
1330
+ {
1331
+ // RHS is a singleton; this is equality
1332
+ expr.id (ID_equal);
1333
+ DATA_INVARIANT (
1334
+ lhs.type () == rhs.type (), " lhs/rhs of in must have same type" );
1335
+ }
1336
+ }
1274
1337
}
1275
1338
1276
1339
/* ******************************************************************\
@@ -1285,28 +1348,50 @@ Function: smv_typecheckt::convert_expr_to
1285
1348
1286
1349
\*******************************************************************/
1287
1350
1288
- void smv_typecheckt::convert_expr_to (exprt &expr, const typet &type )
1351
+ void smv_typecheckt::convert_expr_to (exprt &expr, const typet &dest_type )
1289
1352
{
1290
- PRECONDITION (type. is_not_nil () );
1353
+ const auto &src_type = expr. type ( );
1291
1354
1292
- if (expr.type () != type)
1355
+ PRECONDITION (dest_type.is_not_nil ());
1356
+
1357
+ if (src_type != dest_type)
1293
1358
{
1294
- if (type.id () == ID_signedbv || type.id () == ID_unsignedbv)
1359
+ if (src_type.id () == ID_smv_set && expr.id () == ID_smv_set)
1360
+ {
1361
+ // sets can be assigned to scalars, which yields a nondeterministic
1362
+ // choice
1363
+ std::string identifier =
1364
+ module + " ::var::" + std::to_string (nondet_count++);
1365
+
1366
+ expr.set (ID_identifier, identifier);
1367
+ expr.set (" #smv_nondet_choice" , true );
1368
+
1369
+ expr.id (ID_constraint_select_one);
1370
+ expr.type () = dest_type;
1371
+
1372
+ // apply recursively
1373
+ for (auto &op : expr.operands ())
1374
+ convert_expr_to (op, dest_type);
1375
+
1376
+ return ;
1377
+ }
1378
+
1379
+ if (dest_type.id () == ID_signedbv || dest_type.id () == ID_unsignedbv)
1295
1380
{
1296
1381
// no implicit conversion
1297
1382
}
1298
- else if (type .id () == ID_range)
1383
+ else if (dest_type .id () == ID_range)
1299
1384
{
1300
- if (expr. type () .id () == ID_range)
1385
+ if (src_type .id () == ID_range)
1301
1386
{
1302
1387
// range to range
1303
1388
if (expr.id () == ID_constant)
1304
1389
{
1305
1390
// re-type the constant
1306
1391
auto value = numeric_cast_v<mp_integer>(to_constant_expr (expr));
1307
- if (to_range_type (type ).includes (value))
1392
+ if (to_range_type (dest_type ).includes (value))
1308
1393
{
1309
- expr = from_integer (value, type );
1394
+ expr = from_integer (value, dest_type );
1310
1395
return ;
1311
1396
}
1312
1397
}
@@ -1318,26 +1403,40 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
1318
1403
for (auto &op : expr.operands ())
1319
1404
{
1320
1405
if (!condition)
1321
- convert_expr_to (op, type );
1406
+ convert_expr_to (op, dest_type );
1322
1407
1323
1408
condition = !condition;
1324
1409
}
1325
- expr.type () = type ;
1410
+ expr.type () = dest_type ;
1326
1411
return ;
1327
1412
}
1328
1413
else
1329
1414
{
1330
- expr = typecast_exprt{expr, type };
1415
+ expr = typecast_exprt{expr, dest_type };
1331
1416
return ;
1332
1417
}
1333
1418
}
1419
+ else if (src_type.id () == ID_integer)
1420
+ {
1421
+ // integer to range
1422
+ if (expr.id () == ID_constant)
1423
+ {
1424
+ // re-type the constant
1425
+ auto value = numeric_cast_v<mp_integer>(to_constant_expr (expr));
1426
+ if (to_range_type (dest_type).includes (value))
1427
+ {
1428
+ expr = from_integer (value, dest_type);
1429
+ return ;
1430
+ }
1431
+ }
1432
+ }
1334
1433
}
1335
- else if (type .id () == ID_bool)
1434
+ else if (dest_type .id () == ID_bool)
1336
1435
{
1337
1436
// legacy -- convert 0/1 to false/true
1338
- if (expr. type () .id () == ID_range)
1437
+ if (src_type .id () == ID_range)
1339
1438
{
1340
- auto &range_type = to_range_type (expr. type () );
1439
+ auto &range_type = to_range_type (src_type );
1341
1440
if (range_type.get_from () == 0 && range_type.get_to () == 0 )
1342
1441
{
1343
1442
expr = false_exprt{};
@@ -1350,43 +1449,41 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
1350
1449
}
1351
1450
}
1352
1451
}
1353
- else if (type .id () == ID_enumeration)
1452
+ else if (dest_type .id () == ID_enumeration)
1354
1453
{
1355
- auto &e_type = to_enumeration_type (type );
1454
+ auto &e_type = to_enumeration_type (dest_type );
1356
1455
1357
- if (expr.id () == ID_constant && expr. type () .id () == ID_enumeration)
1456
+ if (expr.id () == ID_constant && src_type .id () == ID_enumeration)
1358
1457
{
1359
- if (is_contained_in (to_enumeration_type (expr. type () ), e_type))
1458
+ if (is_contained_in (to_enumeration_type (src_type ), e_type))
1360
1459
{
1361
1460
// re-type the constant
1362
- expr.type () = type ;
1461
+ expr.type () = dest_type ;
1363
1462
return ;
1364
1463
}
1365
1464
else
1366
1465
{
1367
1466
throw errort ().with_location (expr.find_source_location ())
1368
1467
<< " enum " << to_string (expr) << " not a member of "
1369
- << to_string (type );
1468
+ << to_string (dest_type );
1370
1469
}
1371
1470
}
1372
1471
else if (expr.id () == ID_typecast)
1373
1472
{
1374
1473
// created by type unions
1375
1474
auto &op = to_typecast_expr (expr).op ();
1376
- if (
1377
- expr.type ().id () == ID_enumeration &&
1378
- op.type ().id () == ID_enumeration)
1475
+ if (src_type.id () == ID_enumeration && op.type ().id () == ID_enumeration)
1379
1476
{
1380
- convert_expr_to (op, type );
1477
+ convert_expr_to (op, dest_type );
1381
1478
expr = std::move (op);
1382
1479
}
1383
1480
}
1384
1481
}
1385
1482
1386
1483
throw errort ().with_location (expr.find_source_location ())
1387
- << " Expected expression of type `" << to_string (type )
1484
+ << " Expected expression of type `" << to_string (dest_type )
1388
1485
<< " ', but got expression `" << to_string (expr) << " ', which is of type `"
1389
- << to_string (expr. type () ) << " '" ;
1486
+ << to_string (src_type ) << " '" ;
1390
1487
}
1391
1488
}
1392
1489
0 commit comments