@@ -1001,7 +1001,26 @@ 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
+ }
1014
+ else
1015
+ {
1016
+ typet op_type =
1017
+ type_union (lhs.type (), rhs.type (), expr.source_location ());
1018
+
1019
+ convert_expr_to (lhs, op_type);
1020
+ convert_expr_to (rhs, op_type);
1021
+ }
1022
+
1023
+ expr.type () = bool_typet ();
1005
1024
}
1006
1025
else if (expr.id () == ID_smv_setnotin)
1007
1026
{
@@ -1232,6 +1251,11 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
1232
1251
<< " signed operand must have unsigned word type" ;
1233
1252
}
1234
1253
}
1254
+ else if (expr.id () == ID_smv_set)
1255
+ {
1256
+ // a set literal
1257
+ expr.type () = typet{ID_smv_set};
1258
+ }
1235
1259
else
1236
1260
{
1237
1261
throw errort ().with_location (expr.find_source_location ())
@@ -1285,28 +1309,50 @@ Function: smv_typecheckt::convert_expr_to
1285
1309
1286
1310
\*******************************************************************/
1287
1311
1288
- void smv_typecheckt::convert_expr_to (exprt &expr, const typet &type )
1312
+ void smv_typecheckt::convert_expr_to (exprt &expr, const typet &dest_type )
1289
1313
{
1290
- PRECONDITION (type. is_not_nil () );
1314
+ const auto &src_type = expr. type ( );
1291
1315
1292
- if (expr.type () != type)
1316
+ PRECONDITION (dest_type.is_not_nil ());
1317
+
1318
+ if (src_type != dest_type)
1293
1319
{
1294
- if (type.id () == ID_signedbv || type.id () == ID_unsignedbv)
1320
+ if (src_type.id () == ID_smv_set && expr.id () == ID_smv_set)
1321
+ {
1322
+ // sets can be assigned to scalars, which yields a nondeterministic
1323
+ // choice
1324
+ std::string identifier =
1325
+ module + " ::var::" + std::to_string (nondet_count++);
1326
+
1327
+ expr.set (ID_identifier, identifier);
1328
+ expr.set (" #smv_nondet_choice" , true );
1329
+
1330
+ expr.id (ID_constraint_select_one);
1331
+ expr.type () = dest_type;
1332
+
1333
+ // apply recursively
1334
+ for (auto &op : expr.operands ())
1335
+ convert_expr_to (op, dest_type);
1336
+
1337
+ return ;
1338
+ }
1339
+
1340
+ if (dest_type.id () == ID_signedbv || dest_type.id () == ID_unsignedbv)
1295
1341
{
1296
1342
// no implicit conversion
1297
1343
}
1298
- else if (type .id () == ID_range)
1344
+ else if (dest_type .id () == ID_range)
1299
1345
{
1300
- if (expr. type () .id () == ID_range)
1346
+ if (src_type .id () == ID_range)
1301
1347
{
1302
1348
// range to range
1303
1349
if (expr.id () == ID_constant)
1304
1350
{
1305
1351
// re-type the constant
1306
1352
auto value = numeric_cast_v<mp_integer>(to_constant_expr (expr));
1307
- if (to_range_type (type ).includes (value))
1353
+ if (to_range_type (dest_type ).includes (value))
1308
1354
{
1309
- expr = from_integer (value, type );
1355
+ expr = from_integer (value, dest_type );
1310
1356
return ;
1311
1357
}
1312
1358
}
@@ -1318,26 +1364,40 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
1318
1364
for (auto &op : expr.operands ())
1319
1365
{
1320
1366
if (!condition)
1321
- convert_expr_to (op, type );
1367
+ convert_expr_to (op, dest_type );
1322
1368
1323
1369
condition = !condition;
1324
1370
}
1325
- expr.type () = type ;
1371
+ expr.type () = dest_type ;
1326
1372
return ;
1327
1373
}
1328
1374
else
1329
1375
{
1330
- expr = typecast_exprt{expr, type };
1376
+ expr = typecast_exprt{expr, dest_type };
1331
1377
return ;
1332
1378
}
1333
1379
}
1380
+ else if (src_type.id () == ID_integer)
1381
+ {
1382
+ // integer to range
1383
+ if (expr.id () == ID_constant)
1384
+ {
1385
+ // re-type the constant
1386
+ auto value = numeric_cast_v<mp_integer>(to_constant_expr (expr));
1387
+ if (to_range_type (dest_type).includes (value))
1388
+ {
1389
+ expr = from_integer (value, dest_type);
1390
+ return ;
1391
+ }
1392
+ }
1393
+ }
1334
1394
}
1335
- else if (type .id () == ID_bool)
1395
+ else if (dest_type .id () == ID_bool)
1336
1396
{
1337
1397
// legacy -- convert 0/1 to false/true
1338
- if (expr. type () .id () == ID_range)
1398
+ if (src_type .id () == ID_range)
1339
1399
{
1340
- auto &range_type = to_range_type (expr. type () );
1400
+ auto &range_type = to_range_type (src_type );
1341
1401
if (range_type.get_from () == 0 && range_type.get_to () == 0 )
1342
1402
{
1343
1403
expr = false_exprt{};
@@ -1350,43 +1410,41 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
1350
1410
}
1351
1411
}
1352
1412
}
1353
- else if (type .id () == ID_enumeration)
1413
+ else if (dest_type .id () == ID_enumeration)
1354
1414
{
1355
- auto &e_type = to_enumeration_type (type );
1415
+ auto &e_type = to_enumeration_type (dest_type );
1356
1416
1357
- if (expr.id () == ID_constant && expr. type () .id () == ID_enumeration)
1417
+ if (expr.id () == ID_constant && src_type .id () == ID_enumeration)
1358
1418
{
1359
- if (is_contained_in (to_enumeration_type (expr. type () ), e_type))
1419
+ if (is_contained_in (to_enumeration_type (src_type ), e_type))
1360
1420
{
1361
1421
// re-type the constant
1362
- expr.type () = type ;
1422
+ expr.type () = dest_type ;
1363
1423
return ;
1364
1424
}
1365
1425
else
1366
1426
{
1367
1427
throw errort ().with_location (expr.find_source_location ())
1368
1428
<< " enum " << to_string (expr) << " not a member of "
1369
- << to_string (type );
1429
+ << to_string (dest_type );
1370
1430
}
1371
1431
}
1372
1432
else if (expr.id () == ID_typecast)
1373
1433
{
1374
1434
// created by type unions
1375
1435
auto &op = to_typecast_expr (expr).op ();
1376
- if (
1377
- expr.type ().id () == ID_enumeration &&
1378
- op.type ().id () == ID_enumeration)
1436
+ if (src_type.id () == ID_enumeration && op.type ().id () == ID_enumeration)
1379
1437
{
1380
- convert_expr_to (op, type );
1438
+ convert_expr_to (op, dest_type );
1381
1439
expr = std::move (op);
1382
1440
}
1383
1441
}
1384
1442
}
1385
1443
1386
1444
throw errort ().with_location (expr.find_source_location ())
1387
- << " Expected expression of type `" << to_string (type )
1445
+ << " Expected expression of type `" << to_string (dest_type )
1388
1446
<< " ', but got expression `" << to_string (expr) << " ', which is of type `"
1389
- << to_string (expr. type () ) << " '" ;
1447
+ << to_string (src_type ) << " '" ;
1390
1448
}
1391
1449
}
1392
1450
0 commit comments