Skip to content

Commit ad081dc

Browse files
committed
SMV: flatten hierarchy on parse tree
SMV module flattening is now implemented as an operation on SMV parse trees, as opposed to an operation on a symbol table post type checking.
1 parent f11f972 commit ad081dc

File tree

5 files changed

+74
-177
lines changed

5 files changed

+74
-177
lines changed
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
KNOWNBUG
1+
CORE
22
parameters2.smv
33

44
^EXIT=10$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
This yields a type-checking error.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
use_before_declaration1.smv
3+
^EXIT=0$
4+
^SIGNAL=0$
5+
--
6+
^warning: ignoring
7+
--
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
MODULE main
2+
3+
-- you can use modules before they are declared
4+
SPEC sub.something = 123
5+
6+
VAR sub : my-module;
7+
8+
MODULE my-module
9+
10+
DEFINE something := 123;

src/smvlang/smv_parse_tree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class smv_parse_treet
2929
struct modulet
3030
{
3131
irep_idt name, base_name;
32-
std::list<irep_idt> parameters;
32+
std::vector<irep_idt> parameters;
3333

3434
struct elementt
3535
{

src/smvlang/smv_typecheck.cpp

Lines changed: 55 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class smv_typecheckt:public typecheckt
6060
} modet;
6161

6262
void convert(smv_parse_treet::modulet &);
63+
6364
void create_var_symbols(const smv_parse_treet::modulet::element_listt &);
6465

6566
void collect_define(const equal_exprt &);
@@ -104,16 +105,14 @@ class smv_typecheckt:public typecheckt
104105
smv_parse_treet::modulet &,
105106
const irep_idt &identifier,
106107
const irep_idt &instance,
107-
const exprt::operandst &operands,
108+
const exprt::operandst &arguments,
108109
const source_locationt &);
109110

110111
typet
111112
type_union(const typet &type1, const typet &type2, const source_locationt &);
112113

113114
typedef std::map<irep_idt, exprt> rename_mapt;
114115

115-
void instantiate_rename(exprt &, const rename_mapt &rename_map);
116-
117116
void convert_ports(smv_parse_treet::modulet &, typet &dest);
118117

119118
// for defines
@@ -196,8 +195,14 @@ Function: smv_typecheckt::flatten_hierarchy
196195

197196
void smv_typecheckt::flatten_hierarchy(smv_parse_treet::modulet &smv_module)
198197
{
199-
for(auto &element : smv_module.elements)
198+
// Not using ranged for since we will append to the list we are
199+
// iterating over! This avoids recursion.
200+
for(auto element_it = smv_module.elements.begin();
201+
element_it != smv_module.elements.end();
202+
++element_it)
200203
{
204+
auto &element = *element_it;
205+
201206
if(element.is_var() && element.expr.type().id() == ID_smv_submodule)
202207
{
203208
exprt &inst =
@@ -235,195 +240,66 @@ void smv_typecheckt::instantiate(
235240
smv_parse_treet::modulet &smv_module,
236241
const irep_idt &identifier,
237242
const irep_idt &instance,
238-
const exprt::operandst &operands,
243+
const exprt::operandst &arguments,
239244
const source_locationt &location)
240245
{
241-
symbol_table_baset::symbolst::const_iterator s_it =
242-
symbol_table.symbols.find(identifier);
246+
// Find the module
247+
auto module_it = smv_parse_tree.module_map.find(identifier);
243248

244-
if(s_it==symbol_table.symbols.end())
249+
if(module_it == smv_parse_tree.module_map.end())
245250
{
246251
throw errort().with_location(location)
247252
<< "submodule `" << identifier << "' not found";
248253
}
249254

250-
if(s_it->second.type.id()!=ID_module)
251-
{
252-
throw errort().with_location(location)
253-
<< "submodule `" << identifier << "' not a module";
254-
}
255-
256-
const irept::subt &ports=s_it->second.type.find(ID_ports).get_sub();
257-
258-
// do the arguments/ports
255+
const auto &instantiated_module = *module_it->second;
256+
const auto &parameters = instantiated_module.parameters;
259257

260-
if(ports.size()!=operands.size())
258+
// map the arguments to parameters
259+
if(parameters.size() != arguments.size())
261260
{
262261
throw errort().with_location(location)
263262
<< "submodule `" << identifier << "' has wrong number of arguments";
264263
}
265264

266-
std::set<irep_idt> port_identifiers;
267-
rename_mapt rename_map;
268-
269-
for(std::size_t i = 0; i < ports.size(); i++)
270-
{
271-
const irep_idt &identifier=ports[i].get(ID_identifier);
272-
rename_map.insert(std::pair<irep_idt, exprt>(identifier, operands[i]));
273-
port_identifiers.insert(identifier);
274-
}
275-
276-
// do the variables
277-
278-
std::string new_prefix=
279-
id2string(smv_module.name)+"::var::"+id2string(instance)+".";
280-
281-
std::set<irep_idt> var_identifiers;
282-
283-
for(auto v_it=symbol_table.symbol_module_map.lower_bound(identifier);
284-
v_it!=symbol_table.symbol_module_map.upper_bound(identifier);
285-
v_it++)
286-
{
287-
symbol_table_baset::symbolst::const_iterator s_it2 =
288-
symbol_table.symbols.find(v_it->second);
289-
290-
if(s_it2==symbol_table.symbols.end())
291-
{
292-
throw errort() << "symbol `" << v_it->second << "' not found";
293-
}
294-
295-
if(port_identifiers.find(s_it2->first) != port_identifiers.end())
296-
{
297-
}
298-
else if(s_it2->second.type.id() == ID_module)
299-
{
300-
}
301-
else
302-
{
303-
symbolt symbol(s_it2->second);
304-
305-
symbol.name=new_prefix+id2string(symbol.base_name);
306-
symbol.module=smv_module.name;
307-
308-
if(smv_module.name == "smv::main")
309-
{
310-
symbol.pretty_name =
311-
id2string(instance) + '.' + id2string(symbol.base_name);
312-
}
313-
else
314-
{
315-
symbol.pretty_name = strip_smv_prefix(symbol.name);
316-
}
317-
318-
rename_map.insert(
319-
std::pair<irep_idt, exprt>(s_it2->first, symbol.symbol_expr()));
320-
321-
var_identifiers.insert(symbol.name);
322-
323-
symbol_table.add(symbol);
324-
}
325-
}
326-
327-
// fix values (macros)
328-
329-
for(const auto &v_id : var_identifiers)
330-
{
331-
auto s_it2 = symbol_table.get_writeable(v_id);
332-
333-
if(s_it2==nullptr)
334-
{
335-
throw errort() << "symbol `" << v_id << "' not found";
336-
}
337-
338-
symbolt &symbol=*s_it2;
339-
340-
if(!symbol.value.is_nil())
341-
{
342-
instantiate_rename(symbol.value, rename_map);
343-
typecheck(symbol.value, OTHER);
344-
convert_expr_to(symbol.value, symbol.type);
345-
}
346-
}
347-
348-
// get the transition system
349-
350-
const transt &trans=to_trans_expr(s_it->second.value);
265+
rename_mapt parameter_map;
351266

352-
std::string old_prefix=id2string(s_it->first)+"::var::";
353-
354-
// do the transition system
355-
356-
if(!trans.invar().is_true())
357-
{
358-
exprt tmp(trans.invar());
359-
instantiate_rename(tmp, rename_map);
360-
smv_module.add_invar(tmp);
361-
}
362-
363-
if(!trans.init().is_true())
364-
{
365-
exprt tmp(trans.init());
366-
instantiate_rename(tmp, rename_map);
367-
smv_module.add_init(tmp);
368-
}
369-
370-
if(!trans.trans().is_true())
267+
for(std::size_t i = 0; i < parameters.size(); i++)
371268
{
372-
exprt tmp(trans.trans());
373-
instantiate_rename(tmp, rename_map);
374-
smv_module.add_trans(tmp);
269+
parameter_map.emplace(parameters[i], arguments[i]);
375270
}
376271

377-
}
378-
379-
/*******************************************************************\
380-
381-
Function: smv_typecheckt::instantiate_rename
382-
383-
Inputs:
384-
385-
Outputs:
386-
387-
Purpose:
272+
const std::string prefix = id2string(instance) + '.';
388273

389-
\*******************************************************************/
390-
391-
void smv_typecheckt::instantiate_rename(
392-
exprt &expr,
393-
const rename_mapt &rename_map)
394-
{
395-
for(auto &op : expr.operands())
396-
instantiate_rename(op, rename_map);
397-
398-
if(expr.id()==ID_symbol || expr.id()==ID_next_symbol)
274+
// copy the parse tree elements
275+
for(auto &src_element : instantiated_module.elements)
399276
{
400-
const irep_idt &old_identifier=expr.get(ID_identifier);
401-
bool next=expr.id()==ID_next_symbol;
402-
403-
rename_mapt::const_iterator it=
404-
rename_map.find(old_identifier);
277+
auto copy = src_element;
405278

406-
if(it!=rename_map.end())
407-
{
408-
expr=it->second;
409-
410-
if(next)
279+
// replace the parameter identifiers,
280+
// and add the prefix to non-parameter identifiers
281+
copy.expr.visit_post(
282+
[&parameter_map, &prefix](exprt &expr)
411283
{
412-
if(expr.id()==ID_symbol)
413-
{
414-
expr=it->second;
415-
expr.id(ID_next_symbol);
416-
}
417-
else
284+
if(expr.id() == ID_smv_identifier)
418285
{
419-
throw errort().with_location(expr.find_source_location())
420-
<< "expected symbol expression here, but got "
421-
<< to_string(it->second);
286+
auto identifier = to_smv_identifier_expr(expr).identifier();
287+
auto parameter_it = parameter_map.find(identifier);
288+
if(parameter_it != parameter_map.end())
289+
{
290+
expr = parameter_it->second;
291+
}
292+
else
293+
{
294+
// add the prefix
295+
to_smv_identifier_expr(expr).identifier(
296+
prefix + id2string(identifier));
297+
}
422298
}
423-
}
424-
else
425-
expr=it->second;
426-
}
299+
});
300+
301+
// add to main parse tree
302+
smv_module.elements.push_back(copy);
427303
}
428304
}
429305

@@ -2497,10 +2373,10 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
24972373

24982374
define_map.clear();
24992375

2500-
// check for re-use of variables/defines/parameter identifiers
2501-
variable_checks(smv_module);
2376+
// expand the module hierarchy
2377+
flatten_hierarchy(smv_module);
25022378

2503-
// variables/defines first, can be used before their declaration
2379+
// Now do variables/defines, which can be used before their declaration
25042380
create_var_symbols(smv_module.elements);
25052381

25062382
// transition relation
@@ -2524,8 +2400,6 @@ void smv_typecheckt::convert(smv_parse_treet::modulet &smv_module)
25242400
if(!element.is_var() && !element.is_ivar())
25252401
convert(element);
25262402

2527-
flatten_hierarchy(smv_module);
2528-
25292403
// we first need to collect all the defines
25302404

25312405
for(auto &element : smv_module.elements)
@@ -2631,6 +2505,13 @@ Function: smv_typecheckt::typecheck
26312505

26322506
void smv_typecheckt::typecheck()
26332507
{
2508+
if(module != "smv::main")
2509+
return;
2510+
2511+
// check all modules for duplicate identifiers
2512+
for(auto &module : smv_parse_tree.module_list)
2513+
variable_checks(module);
2514+
26342515
auto it = smv_parse_tree.module_map.find(module);
26352516

26362517
if(it == smv_parse_tree.module_map.end())

0 commit comments

Comments
 (0)