Skip to content

Commit 28a3c20

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 a93aa31 commit 28a3c20

File tree

8 files changed

+245
-105
lines changed

8 files changed

+245
-105
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
@@ -21,6 +21,7 @@ IREP_ID_ONE(smv_abs)
2121
IREP_ID_ONE(smv_bitimplies)
2222
IREP_ID_ONE(smv_bool)
2323
IREP_ID_ONE(smv_count)
24+
IREP_ID_ONE(smv_enumeration)
2425
IREP_ID_ONE(smv_extend)
2526
IREP_ID_ONE(smv_max)
2627
IREP_ID_ONE(smv_min)

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
}
@@ -903,15 +909,15 @@ std::string type2smv(const typet &type, const namespacet &ns)
903909
code += type2smv(to_array_type(type).element_type(), ns);
904910
return code;
905911
}
906-
else if(type.id()==ID_enumeration)
912+
else if(type.id() == ID_smv_enumeration)
907913
{
908-
const irept::subt &elements=to_enumeration_type(type).elements();
914+
auto elements = to_smv_enumeration_type(type).elements();
909915
std::string code = "{ ";
910916
bool first=true;
911917
for(auto &element : elements)
912918
{
913919
if(first) first=false; else code+=", ";
914-
code += element.id_string();
920+
code += id2string(element);
915921
}
916922
code+=" }";
917923
return code;

src/smvlang/parser.y

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ parameter_list:
642642

643643
enum_list : enum_element
644644
{
645-
init($$, ID_enumeration);
645+
init($$, ID_smv_enumeration);
646646
stack_expr($$).add(ID_elements).get_sub().push_back(irept(stack_expr($1).id()));
647647
}
648648
| enum_list ',' enum_element
@@ -946,7 +946,7 @@ variable_identifier: complex_identifier
946946
else if(is_enum)
947947
{
948948
init($$, ID_constant);
949-
stack_expr($$).type()=typet(ID_enumeration);
949+
stack_expr($$).type()=typet(ID_smv_enumeration);
950950
stack_expr($$).set(ID_value, id);
951951
}
952952
else // not an enum, probably a variable

src/smvlang/smv_typecheck.cpp

Lines changed: 78 additions & 95 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)
@@ -1528,6 +1474,30 @@ void smv_typecheckt::lower_node(exprt &expr) const
15281474
auto one = from_integer(1, expr.type());
15291475
expr = if_exprt{op, std::move(one), std::move(zero)};
15301476
}
1477+
1478+
// lower the type
1479+
lower(expr.type());
1480+
}
1481+
1482+
/*******************************************************************\
1483+
1484+
Function: smv_typecheckt::lower
1485+
1486+
Inputs:
1487+
1488+
Outputs:
1489+
1490+
Purpose:
1491+
1492+
\*******************************************************************/
1493+
1494+
void smv_typecheckt::lower(typet &type) const
1495+
{
1496+
// lower the type
1497+
if(type.id() == ID_smv_enumeration)
1498+
{
1499+
type.id(ID_enumeration);
1500+
}
15311501
}
15321502

15331503
/*******************************************************************\
@@ -1643,33 +1613,40 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &dest_type)
16431613
}
16441614
}
16451615
}
1646-
else if(dest_type.id() == ID_enumeration)
1616+
else if(dest_type.id() == ID_smv_enumeration)
16471617
{
1648-
auto &e_type = to_enumeration_type(dest_type);
1618+
auto &dest_e_type = to_smv_enumeration_type(dest_type);
16491619

1650-
if(expr.id() == ID_constant && src_type.id() == ID_enumeration)
1620+
if(expr.type().id() == ID_smv_enumeration)
16511621
{
1652-
if(is_contained_in(to_enumeration_type(src_type), e_type))
1622+
// subset?
1623+
if(to_smv_enumeration_type(expr.type()).is_subset_of(dest_e_type))
16531624
{
1654-
// re-type the constant
1655-
expr.type() = dest_type;
1656-
return;
1657-
}
1658-
else
1659-
{
1660-
throw errort().with_location(expr.find_source_location())
1661-
<< "enum " << to_string(expr) << " not a member of "
1662-
<< to_string(dest_type);
1663-
}
1664-
}
1665-
else if(expr.id() == ID_typecast)
1666-
{
1667-
// created by type unions
1668-
auto &op = to_typecast_expr(expr).op();
1669-
if(src_type.id() == ID_enumeration && op.type().id() == ID_enumeration)
1670-
{
1671-
convert_expr_to(op, dest_type);
1672-
expr = std::move(op);
1625+
// yes, it's a subset
1626+
if(expr.is_constant())
1627+
{
1628+
// re-type the constant
1629+
expr.type() = dest_type;
1630+
return;
1631+
}
1632+
else if(expr.id() == ID_typecast)
1633+
{
1634+
// created by type unions
1635+
auto &op = to_typecast_expr(expr).op();
1636+
if(
1637+
expr.type().id() == ID_smv_enumeration &&
1638+
op.type().id() == ID_smv_enumeration)
1639+
{
1640+
convert_expr_to(op, dest_type);
1641+
expr = std::move(op);
1642+
return;
1643+
}
1644+
}
1645+
else // anything else
1646+
{
1647+
expr = typecast_exprt{std::move(expr), dest_type};
1648+
return;
1649+
}
16731650
}
16741651
}
16751652
}
@@ -2167,9 +2144,6 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
21672144
transt{ID_trans, conjunction(trans_invar), conjunction(trans_init),
21682145
conjunction(trans_trans), module_symbol.type};
21692146

2170-
// lowering
2171-
lower(module_symbol.value);
2172-
21732147
module_symbol.pretty_name = strip_smv_prefix(module_symbol.name);
21742148

21752149
symbol_table.add(module_symbol);
@@ -2208,12 +2182,21 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
22082182
spec_symbol.pretty_name = strip_smv_prefix(spec_symbol.name);
22092183

22102184
// lowering
2211-
lower(spec_symbol.value);
22122185

22132186
symbol_table.add(spec_symbol);
22142187
}
22152188
}
22162189
}
2190+
2191+
// lowering
2192+
for(auto v_it=symbol_table.symbol_module_map.lower_bound(smv_module.name);
2193+
v_it!=symbol_table.symbol_module_map.upper_bound(smv_module.name);
2194+
v_it++)
2195+
{
2196+
auto &symbol = symbol_table.get_writeable_ref(v_it->second);
2197+
lower(symbol.type);
2198+
lower(symbol.value);
2199+
}
22172200
}
22182201

22192202
/*******************************************************************\

0 commit comments

Comments
 (0)