Skip to content

Commit b2da631

Browse files
committed
introduce SMV enumeration type
SMV enumerations behave differently from enumeration_typet; hence, this introduces smv_enumeration_typet, which is subsequently lowered to enumeration_typet.
1 parent b0016ca commit b2da631

File tree

8 files changed

+245
-107
lines changed

8 files changed

+245
-107
lines changed

regression/smv/enums/enum3.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
enum3.smv
33

4-
^file .* line 7: enum c not a member of \{ a, b \}$
4+
^file .* line 7: Expected expression of type `\{ a, b \}', but got expression `c', which is of type `\{ c \}'$
55
^EXIT=2$
66
^SIGNAL=0$
77
--

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ IREP_ID_ONE(E)
1818
IREP_ID_ONE(G)
1919
IREP_ID_ONE(X)
2020
IREP_ID_ONE(smv_bitimplies)
21+
IREP_ID_ONE(smv_enumeration)
2122
IREP_ID_ONE(smv_extend)
2223
IREP_ID_ONE(smv_next)
2324
IREP_ID_ONE(smv_iff)

src/smvlang/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ SRC = smv_expr.cpp \
22
smv_language.cpp \
33
smv_parser.cpp \
44
smv_typecheck.cpp \
5+
smv_types.cpp \
56
expr2smv.cpp \
67
smv_y.tab.cpp \
78
lex.yy.cpp \

src/smvlang/expr2smv.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include <util/mathematical_types.h>
1313

1414
#include "smv_expr.h"
15+
#include "smv_types.h"
1516

1617
/*******************************************************************\
1718
@@ -337,6 +338,12 @@ expr2smvt::resultt expr2smvt::convert_typecast(const typecast_exprt &expr)
337338
return convert_rec(smv_resize_exprt{expr.op(), dest_width, dest_type});
338339
}
339340
}
341+
else if(
342+
src_type.id() == ID_smv_enumeration && dest_type.id() == ID_smv_enumeration)
343+
{
344+
// added by SMV typechecker, implicit
345+
return convert_rec(expr.op());
346+
}
340347
else
341348
return convert_norep(expr);
342349
}
@@ -593,10 +600,9 @@ expr2smvt::resultt expr2smvt::convert_constant(const constant_exprt &src)
593600
else
594601
dest+="FALSE";
595602
}
596-
else if(type.id()==ID_integer ||
597-
type.id()==ID_natural ||
598-
type.id()==ID_range ||
599-
type.id()==ID_enumeration)
603+
else if(
604+
type.id() == ID_integer || type.id() == ID_natural ||
605+
type.id() == ID_range || type.id() == ID_smv_enumeration)
600606
{
601607
dest = id2string(src.get_value());
602608
}
@@ -885,15 +891,15 @@ std::string type2smv(const typet &type, const namespacet &ns)
885891
code += type2smv(to_array_type(type).element_type(), ns);
886892
return code;
887893
}
888-
else if(type.id()==ID_enumeration)
894+
else if(type.id() == ID_smv_enumeration)
889895
{
890-
const irept::subt &elements=to_enumeration_type(type).elements();
896+
auto elements = to_smv_enumeration_type(type).elements();
891897
std::string code = "{ ";
892898
bool first=true;
893899
for(auto &element : elements)
894900
{
895901
if(first) first=false; else code+=", ";
896-
code += element.id_string();
902+
code += id2string(element);
897903
}
898904
code+=" }";
899905
return code;

src/smvlang/parser.y

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ module_type_specifier:
522522

523523
enum_list : enum_element
524524
{
525-
init($$, ID_enumeration);
525+
init($$, ID_smv_enumeration);
526526
stack_expr($$).add(ID_elements).get_sub().push_back(irept(stack_expr($1).id()));
527527
}
528528
| enum_list ',' enum_element
@@ -808,7 +808,7 @@ variable_identifier: complex_identifier
808808
else if(is_enum)
809809
{
810810
init($$, ID_constant);
811-
stack_expr($$).type()=typet(ID_enumeration);
811+
stack_expr($$).type()=typet(ID_smv_enumeration);
812812
stack_expr($$).set(ID_value, id);
813813
}
814814
else // not an enum, probably a variable

src/smvlang/smv_typecheck.cpp

Lines changed: 78 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include "expr2smv.h"
2020
#include "smv_expr.h"
2121
#include "smv_range.h"
22+
#include "smv_types.h"
2223

2324
#include <algorithm>
2425
#include <cassert>
@@ -83,8 +84,6 @@ class smv_typecheckt:public typecheckt
8384

8485
void check_type(const typet &);
8586
smv_ranget convert_type(const typet &);
86-
static bool
87-
is_contained_in(const enumeration_typet &, const enumeration_typet &);
8887

8988
void convert(smv_parse_treet::modulet::itemt &);
9089
void typecheck(smv_parse_treet::modulet::itemt &);
@@ -142,6 +141,8 @@ class smv_typecheckt:public typecheckt
142141

143142
void lower_node(exprt &) const;
144143

144+
void lower(typet &) const;
145+
145146
void lower(exprt &expr) const
146147
{
147148
expr.visit_post([this](exprt &expr) { lower_node(expr); });
@@ -150,40 +151,6 @@ class smv_typecheckt:public typecheckt
150151

151152
/*******************************************************************\
152153
153-
Function: smv_typecheckt::is_contained_in
154-
155-
Inputs:
156-
157-
Outputs:
158-
159-
Purpose:
160-
161-
\*******************************************************************/
162-
163-
bool smv_typecheckt::is_contained_in(
164-
const enumeration_typet &type1,
165-
const enumeration_typet &type2)
166-
{
167-
// This is quadratic.
168-
for(auto &element1 : type1.elements())
169-
{
170-
bool found = false;
171-
for(auto &element2 : type2.elements())
172-
if(element1.id() == element2.id())
173-
{
174-
found = true;
175-
break;
176-
}
177-
178-
if(!found)
179-
return false;
180-
}
181-
182-
return true;
183-
}
184-
185-
/*******************************************************************\
186-
187154
Function: smv_typecheckt::convert_ports
188155
189156
Inputs:
@@ -499,15 +466,15 @@ smv_ranget smv_typecheckt::convert_type(const typet &src)
499466
{
500467
return smv_ranget::from_type(to_range_type(src));
501468
}
502-
else if(src.id()==ID_enumeration)
469+
else if(src.id() == ID_smv_enumeration)
503470
{
504471
smv_ranget dest;
505472

506473
dest.from=0;
507474

508-
std::size_t number_of_elements=
509-
to_enumeration_type(src).elements().size();
510-
475+
std::size_t number_of_elements =
476+
to_smv_enumeration_type(src).elements().size();
477+
511478
if(number_of_elements==0)
512479
dest.to=0;
513480
else
@@ -557,36 +524,16 @@ typet smv_typecheckt::type_union(
557524
}
558525

559526
// both enums?
560-
if(type1.id()==ID_enumeration && type2.id()==ID_enumeration)
527+
if(type1.id() == ID_smv_enumeration && type2.id() == ID_smv_enumeration)
561528
{
562-
auto &e_type1 = to_enumeration_type(type1);
563-
auto &e_type2 = to_enumeration_type(type2);
564-
565-
if(is_contained_in(e_type2, e_type1))
566-
return type1;
567-
568-
if(is_contained_in(e_type1, e_type2))
569-
return type2;
570-
571-
// make union
572-
std::set<irep_idt> enum_set;
573-
574-
for(auto &e : e_type1.elements())
575-
enum_set.insert(e.id());
529+
auto &e_type1 = to_smv_enumeration_type(type1);
530+
auto &e_type2 = to_smv_enumeration_type(type2);
576531

577-
for(auto &e : e_type2.elements())
578-
enum_set.insert(e.id());
579-
580-
enumeration_typet union_type;
581-
union_type.elements().reserve(enum_set.size());
582-
for(auto &e : enum_set)
583-
union_type.elements().push_back(irept{e});
584-
585-
return std::move(union_type);
532+
return ::type_union(e_type1, e_type2);
586533
}
587534

588535
// one of them enum?
589-
if(type1.id() == ID_enumeration || type2.id() == ID_enumeration)
536+
if(type1.id() == ID_smv_enumeration || type2.id() == ID_smv_enumeration)
590537
{
591538
throw errort().with_location(source_location)
592539
<< "no type union for types " << to_string(type1) << " and "
@@ -869,10 +816,9 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
869816
mp_integer int_value = string2integer(id2string(value));
870817
expr.type() = range_typet{int_value, int_value};
871818
}
872-
else if(type.id() == ID_enumeration)
819+
else if(type.id() == ID_smv_enumeration)
873820
{
874-
auto t = enumeration_typet{};
875-
t.elements().push_back(irept{value});
821+
auto t = smv_enumeration_typet{{value}};
876822
expr.type() = std::move(t);
877823
}
878824
else if(type.id() == ID_bool)
@@ -1253,6 +1199,9 @@ Function: smv_typecheckt::lower_node
12531199

12541200
void smv_typecheckt::lower_node(exprt &expr) const
12551201
{
1202+
// lower the type
1203+
lower(expr.type());
1204+
12561205
if(expr.id() == ID_smv_extend)
12571206
{
12581207
auto &smv_extend = to_smv_extend_expr(expr);
@@ -1275,6 +1224,27 @@ void smv_typecheckt::lower_node(exprt &expr) const
12751224

12761225
/*******************************************************************\
12771226
1227+
Function: smv_typecheckt::lower
1228+
1229+
Inputs:
1230+
1231+
Outputs:
1232+
1233+
Purpose:
1234+
1235+
\*******************************************************************/
1236+
1237+
void smv_typecheckt::lower(typet &type) const
1238+
{
1239+
// lower the type
1240+
if(type.id() == ID_smv_enumeration)
1241+
{
1242+
type.id(ID_enumeration);
1243+
}
1244+
}
1245+
1246+
/*******************************************************************\
1247+
12781248
Function: smv_typecheckt::convert_expr_to
12791249
12801250
Inputs:
@@ -1350,35 +1320,40 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
13501320
}
13511321
}
13521322
}
1353-
else if(type.id() == ID_enumeration)
1323+
else if(type.id() == ID_smv_enumeration)
13541324
{
1355-
auto &e_type = to_enumeration_type(type);
1325+
auto &e_type = to_smv_enumeration_type(type);
13561326

1357-
if(expr.id() == ID_constant && expr.type().id() == ID_enumeration)
1327+
if(expr.type().id() == ID_smv_enumeration)
13581328
{
1359-
if(is_contained_in(to_enumeration_type(expr.type()), e_type))
1329+
// subset?
1330+
if(to_smv_enumeration_type(expr.type()).is_subset_of(e_type))
13601331
{
1361-
// re-type the constant
1362-
expr.type() = type;
1363-
return;
1364-
}
1365-
else
1366-
{
1367-
throw errort().with_location(expr.find_source_location())
1368-
<< "enum " << to_string(expr) << " not a member of "
1369-
<< to_string(type);
1370-
}
1371-
}
1372-
else if(expr.id() == ID_typecast)
1373-
{
1374-
// created by type unions
1375-
auto &op = to_typecast_expr(expr).op();
1376-
if(
1377-
expr.type().id() == ID_enumeration &&
1378-
op.type().id() == ID_enumeration)
1379-
{
1380-
convert_expr_to(op, type);
1381-
expr = std::move(op);
1332+
// yes, it's a subset
1333+
if(expr.is_constant())
1334+
{
1335+
// re-type the constant
1336+
expr.type() = type;
1337+
return;
1338+
}
1339+
else if(expr.id() == ID_typecast)
1340+
{
1341+
// created by type unions
1342+
auto &op = to_typecast_expr(expr).op();
1343+
if(
1344+
expr.type().id() == ID_smv_enumeration &&
1345+
op.type().id() == ID_smv_enumeration)
1346+
{
1347+
convert_expr_to(op, type);
1348+
expr = std::move(op);
1349+
return;
1350+
}
1351+
}
1352+
else // anything else
1353+
{
1354+
expr = typecast_exprt{std::move(expr), type};
1355+
return;
1356+
}
13821357
}
13831358
}
13841359
}
@@ -1875,9 +1850,6 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
18751850
transt{ID_trans, conjunction(trans_invar), conjunction(trans_init),
18761851
conjunction(trans_trans), module_symbol.type};
18771852

1878-
// lowering
1879-
lower(module_symbol.value);
1880-
18811853
module_symbol.pretty_name = strip_smv_prefix(module_symbol.name);
18821854

18831855
symbol_table.add(module_symbol);
@@ -1916,12 +1888,21 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
19161888
spec_symbol.pretty_name = strip_smv_prefix(spec_symbol.name);
19171889

19181890
// lowering
1919-
lower(spec_symbol.value);
19201891

19211892
symbol_table.add(spec_symbol);
19221893
}
19231894
}
19241895
}
1896+
1897+
// lowering
1898+
for(auto v_it=symbol_table.symbol_module_map.lower_bound(smv_module.name);
1899+
v_it!=symbol_table.symbol_module_map.upper_bound(smv_module.name);
1900+
v_it++)
1901+
{
1902+
auto &symbol = symbol_table.get_writeable_ref(v_it->second);
1903+
lower(symbol.type);
1904+
lower(symbol.value);
1905+
}
19251906
}
19261907

19271908
/*******************************************************************\

0 commit comments

Comments
 (0)