@@ -90,6 +90,7 @@ class smv_typecheckt:public typecheckt
9090 void typecheck (smv_parse_treet::modulet::itemt &);
9191 void typecheck_expr_rec (exprt &, modet);
9292 void convert_expr_to (exprt &, const typet &dest);
93+ constant_exprt convert_word_constant (const constant_exprt &);
9394
9495 smv_parse_treet::modulet *modulep;
9596
@@ -582,6 +583,126 @@ void smv_typecheckt::typecheck(exprt &expr, modet mode)
582583
583584/* ******************************************************************\
584585
586+ Function: convert_word_constant
587+
588+ Inputs:
589+
590+ Outputs:
591+
592+ Purpose:
593+
594+ \*******************************************************************/
595+
596+ constant_exprt
597+ smv_typecheckt::convert_word_constant (const constant_exprt &src_expr)
598+ {
599+ auto &src = id2string (src_expr.get_value ());
600+
601+ DATA_INVARIANT (src[0 ] == ' 0' , " word constant grammar" );
602+
603+ std::size_t index = 1 ;
604+ bool is_signed = false ;
605+
606+ DATA_INVARIANT (index < src.size (), " word constant length" );
607+
608+ switch (src[index])
609+ {
610+ case ' s' :
611+ case ' S' :
612+ is_signed = true ;
613+ index++;
614+ break ;
615+
616+ case ' u' :
617+ case ' U' :
618+ // this is the default
619+ index++;
620+ break ;
621+
622+ default :;
623+ }
624+
625+ DATA_INVARIANT (index < src.size (), " word constant length" );
626+
627+ unsigned base;
628+ switch (src[index])
629+ {
630+ case ' d' :
631+ case ' D' :
632+ base = 10 ;
633+ break ;
634+
635+ case ' h' :
636+ case ' H' :
637+ base = 16 ;
638+ break ;
639+
640+ case ' b' :
641+ case ' B' :
642+ base = 2 ;
643+ break ;
644+
645+ case ' o' :
646+ case ' O' :
647+ base = 8 ;
648+ break ;
649+
650+ default :
651+ DATA_INVARIANT (false , " word constant base" );
652+ }
653+
654+ index++;
655+
656+ DATA_INVARIANT (index < src.size (), " word constant length" );
657+
658+ std::optional<mp_integer> bits = {};
659+
660+ // optional number of bits
661+ if (isdigit (src[index]))
662+ {
663+ std::string bits_str;
664+ for (; index < src.size () && isdigit (src[index]); index++)
665+ {
666+ bits_str += src[index];
667+ }
668+
669+ bits = string2integer (bits_str);
670+ }
671+
672+ std::string digits;
673+ digits.reserve (src.size ());
674+
675+ for (; index < src.size (); index++)
676+ {
677+ if (src[index] != ' _' )
678+ digits.push_back (src[index]);
679+ }
680+
681+ if (!bits.has_value ())
682+ {
683+ if (base == 10 )
684+ throw errort{}.with_location (src_expr.source_location ())
685+ << " decimal word constant without width" ;
686+ else if (base == 2 )
687+ bits = digits.size ();
688+ else if (base == 8 )
689+ bits = digits.size () * 3 ;
690+ else if (base == 16 )
691+ bits = digits.size () * 4 ;
692+ }
693+
694+ auto digits_int = string2integer (digits, base);
695+
696+ auto type =
697+ bitvector_typet{is_signed ? ID_signedbv : ID_unsignedbv, bits.value ()};
698+
699+ auto result = from_integer (digits_int, type);
700+ result.add_source_location () = src_expr.source_location ();
701+ return result;
702+ }
703+
704+ /* ******************************************************************\
705+
585706Function: smv_typecheckt::typecheck_expr_rec
586707
587708 Inputs:
@@ -845,6 +966,11 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
845966 {
846967 // good as is
847968 }
969+ else if (type.id () == ID_smv_word_constant)
970+ {
971+ // turn into signedbv/unsignedbv
972+ expr = convert_word_constant (to_constant_expr (expr));
973+ }
848974 else
849975 {
850976 PRECONDITION (false );
0 commit comments