Skip to content

Commit 61bd6c2

Browse files
committed
SMV: allow any expression in SMV types
This extends the grammar to allow any expressions as the size of arrays and as the width of word types. This matches the NuSMV manual. The type checker enforces that these are constants.
1 parent 4f930c8 commit 61bd6c2

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
invalid_width1.smv
3+
4+
^file .* line 6: expected constant expression$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
MODULE main
2+
3+
VAR width : 1..10;
4+
5+
-- The width must be constant
6+
VAR word_var : word[width];

src/smvlang/parser.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -556,25 +556,25 @@ type_specifier:
556556
;
557557

558558
simple_type_specifier:
559-
array_Token integer_constant DOTDOT_Token integer_constant of_Token simple_type_specifier
559+
array_Token basic_expr DOTDOT_Token basic_expr of_Token simple_type_specifier
560560
{
561561
init($$, ID_smv_array);
562562
stack_type($$).set(ID_from, stack_expr($2));
563563
stack_type($$).set(ID_to, stack_expr($4));
564564
stack_type($$).add_subtype()=stack_type($6);
565565
}
566566
| boolean_Token { init($$, ID_bool); }
567-
| word_Token '[' integer_constant ']'
567+
| word_Token '[' basic_expr ']'
568568
{
569569
init($$, ID_smv_word);
570570
stack_type($$).set(ID_width, stack_expr($3));
571571
}
572-
| signed_Token word_Token '[' integer_constant ']'
572+
| signed_Token word_Token '[' basic_expr ']'
573573
{
574574
init($$, ID_smv_signed_word);
575575
stack_type($$).set(ID_width, stack_expr($4));
576576
}
577-
| unsigned_Token word_Token '[' integer_constant ']'
577+
| unsigned_Token word_Token '[' basic_expr ']'
578578
{
579579
init($$, ID_smv_unsigned_word);
580580
stack_type($$).set(ID_width, stack_expr($4));

src/smvlang/smv_typecheck.cpp

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ class smv_typecheckt:public typecheckt
144144
return id;
145145
}
146146

147+
mp_integer require_integer_constant(const irept &) const;
148+
147149
void lower_node(exprt &) const;
148150

149151
void lower(typet &) const;
@@ -363,6 +365,36 @@ void smv_typecheckt::instantiate(
363365

364366
/*******************************************************************\
365367
368+
Function: smv_typecheckt::require_integer_constant
369+
370+
Inputs:
371+
372+
Outputs:
373+
374+
Purpose:
375+
376+
\*******************************************************************/
377+
378+
mp_integer smv_typecheckt::require_integer_constant(const irept &irep) const
379+
{
380+
auto &as_expr = static_cast<const exprt &>(irep);
381+
if(as_expr.id() != ID_constant)
382+
{
383+
throw errort().with_location(as_expr.source_location())
384+
<< "expected constant expression";
385+
}
386+
387+
if(as_expr.type().id() != ID_integer)
388+
{
389+
throw errort().with_location(as_expr.source_location())
390+
<< "expected integer expression";
391+
}
392+
393+
return numeric_cast_v<mp_integer>(to_constant_expr(as_expr));
394+
}
395+
396+
/*******************************************************************\
397+
366398
Function: smv_typecheckt::check_type
367399
368400
Inputs:
@@ -377,10 +409,8 @@ void smv_typecheckt::check_type(typet &type)
377409
{
378410
if(type.id() == ID_smv_array)
379411
{
380-
auto from = numeric_cast_v<mp_integer>(
381-
to_constant_expr(static_cast<const exprt &>(type.find(ID_from))));
382-
auto to = numeric_cast_v<mp_integer>(
383-
to_constant_expr(static_cast<const exprt &>(type.find(ID_to))));
412+
auto from = require_integer_constant(type.find(ID_from));
413+
auto to = require_integer_constant(type.find(ID_to));
384414

385415
if(to < from)
386416
throw errort().with_location(type.source_location())
@@ -402,10 +432,8 @@ void smv_typecheckt::check_type(typet &type)
402432
}
403433
else if(type.id() == ID_smv_range)
404434
{
405-
auto from = numeric_cast_v<mp_integer>(
406-
to_constant_expr(static_cast<const exprt &>(type.find(ID_from))));
407-
auto to = numeric_cast_v<mp_integer>(
408-
to_constant_expr(static_cast<const exprt &>(type.find(ID_to))));
435+
auto from = require_integer_constant(type.find(ID_from));
436+
auto to = require_integer_constant(type.find(ID_to));
409437

410438
if(from > to)
411439
throw errort().with_location(type.source_location()) << "range is empty";
@@ -416,8 +444,7 @@ void smv_typecheckt::check_type(typet &type)
416444
}
417445
else if(type.id() == ID_smv_signed_word)
418446
{
419-
auto width = numeric_cast_v<mp_integer>(
420-
to_constant_expr(static_cast<const exprt &>(type.find(ID_width))));
447+
auto width = require_integer_constant(type.find(ID_width));
421448

422449
if(width < 1)
423450
throw errort().with_location(type.source_location())
@@ -428,8 +455,7 @@ void smv_typecheckt::check_type(typet &type)
428455
}
429456
else if(type.id() == ID_smv_word || type.id() == ID_smv_unsigned_word)
430457
{
431-
auto width = numeric_cast_v<mp_integer>(
432-
to_constant_expr(static_cast<const exprt &>(type.find(ID_width))));
458+
auto width = require_integer_constant(type.find(ID_width));
433459

434460
if(width < 1)
435461
throw errort().with_location(type.source_location())

0 commit comments

Comments
 (0)