@@ -584,7 +584,7 @@ impl Expr {
584584 // Check that each formal field has an value
585585 assert ! (
586586 fields. iter( ) . zip( values. iter( ) ) . all( |( f, v) | f. typ( ) == * v. typ( ) ) ,
587- "Error in struct_expr\n \t {:?}\n \t {:?}" ,
587+ "Error in struct_expr; value type does not match field type. \n \t {:?}\n \t {:?}" ,
588588 typ,
589589 values
590590 ) ;
@@ -593,20 +593,25 @@ impl Expr {
593593
594594 /// Struct initializer
595595 /// `struct foo the_foo = >>> {.field1 = val1, .field2 = val2, ... } <<<`
596- /// Note that only the NON padding fields should be explicitiy given.
596+ /// Note that only the NON padding fields should be explicitly given.
597597 /// Padding fields are automatically inserted using the type from the `SymbolTable`
598598 pub fn struct_expr (
599599 typ : Type ,
600600 mut components : BTreeMap < String , Expr > ,
601601 symbol_table : & SymbolTable ,
602602 ) -> Self {
603- assert ! ( typ. is_struct_tag( ) , "Error in struct_expr\n \t {:?}\n \t {:?}" , typ, components) ;
603+ assert ! (
604+ typ. is_struct_tag( ) ,
605+ "Error in struct_expr; must be given a struct_tag.\n \t {:?}\n \t {:?}" ,
606+ typ,
607+ components
608+ ) ;
604609 let fields = symbol_table. lookup_fields_in_type ( & typ) . unwrap ( ) ;
605610 let non_padding_fields: Vec < _ > = fields. iter ( ) . filter ( |x| !x. is_padding ( ) ) . collect ( ) ;
606611 assert_eq ! (
607612 non_padding_fields. len( ) ,
608613 components. len( ) ,
609- "Error in struct_expr\n \t {:?}\n \t {:?}" ,
614+ "Error in struct_expr; mismatch in number of fields and components. \n \t {:?}\n \t {:?}" ,
610615 typ,
611616 components
612617 ) ;
@@ -658,7 +663,7 @@ impl Expr {
658663
659664 /// Struct initializer
660665 /// `struct foo the_foo = >>> {field1, field2, ... } <<<`
661- /// Note that only the NON padding fields should be explicitiy given.
666+ /// Note that only the NON padding fields should be explicitly given.
662667 /// Padding fields are automatically inserted using the type from the `SymbolTable`
663668 pub fn struct_expr_from_values (
664669 typ : Type ,
@@ -667,7 +672,7 @@ impl Expr {
667672 ) -> Self {
668673 assert ! (
669674 typ. is_struct_tag( ) ,
670- "Error in struct_expr\n \t {:?}\n \t {:?}" ,
675+ "Error in struct_expr; must be given struct_tag. \n \t {:?}\n \t {:?}" ,
671676 typ,
672677 non_padding_values
673678 ) ;
@@ -676,7 +681,7 @@ impl Expr {
676681 assert_eq ! (
677682 non_padding_fields. len( ) ,
678683 non_padding_values. len( ) ,
679- "Error in struct_expr\n \t {:?}\n \t {:?}" ,
684+ "Error in struct_expr; mismatch in number of fields and values. \n \t {:?}\n \t {:?}" ,
680685 typ,
681686 non_padding_values
682687 ) ;
@@ -685,7 +690,7 @@ impl Expr {
685690 . iter( )
686691 . zip( non_padding_values. iter( ) )
687692 . all( |( f, v) | f. field_typ( ) . unwrap( ) == v. typ( ) ) ,
688- "Error in struct_expr\n \t {:?}\n \t {:?}" ,
693+ "Error in struct_expr; value type does not match field type. \n \t {:?}\n \t {:?}" ,
689694 typ,
690695 non_padding_values
691696 ) ;
@@ -698,6 +703,40 @@ impl Expr {
698703 Expr :: struct_expr_with_explicit_padding ( typ, fields, values)
699704 }
700705
706+ /// Struct initializer
707+ /// `struct foo the_foo = >>> {field1, padding2, field3, ... } <<<`
708+ /// Note that padding fields should be explicitly given.
709+ /// This would be used when the values and padding have already been combined,
710+ /// e.g. when extracting the values out of an existing struct expr (see transformer.rs)
711+ pub fn struct_expr_from_padded_values (
712+ typ : Type ,
713+ values : Vec < Expr > ,
714+ symbol_table : & SymbolTable ,
715+ ) -> Self {
716+ assert ! (
717+ typ. is_struct_tag( ) ,
718+ "Error in struct_expr; must be given struct_tag.\n \t {:?}\n \t {:?}" ,
719+ typ,
720+ values
721+ ) ;
722+ let fields = symbol_table. lookup_fields_in_type ( & typ) . unwrap ( ) ;
723+ assert_eq ! (
724+ fields. len( ) ,
725+ values. len( ) ,
726+ "Error in struct_expr; mismatch in number of padded fields and padded values.\n \t {:?}\n \t {:?}" ,
727+ typ,
728+ values
729+ ) ;
730+ assert ! (
731+ fields. iter( ) . zip( values. iter( ) ) . all( |( f, v) | & f. typ( ) == v. typ( ) ) ,
732+ "Error in struct_expr; value type does not match field type.\n \t {:?}\n \t {:?}" ,
733+ typ,
734+ values
735+ ) ;
736+
737+ Expr :: struct_expr_with_explicit_padding ( typ, fields, values)
738+ }
739+
701740 /// `identifier`
702741 pub fn symbol_expression ( identifier : String , typ : Type ) -> Self {
703742 expr ! ( Symbol { identifier } , typ)
@@ -1205,6 +1244,12 @@ impl Expr {
12051244 res. overflowed . ternary ( saturating_val, res. result )
12061245 }
12071246
1247+ /// `"s"`
1248+ /// only to be used when manually wrapped in `.array_to_ptr()`
1249+ pub fn raw_string_constant ( s : & str ) -> Self {
1250+ expr ! ( StringConstant { s: s. to_string( ) } , Type :: c_char( ) . array_of( s. len( ) + 1 ) )
1251+ }
1252+
12081253 /// `"s"`
12091254 pub fn string_constant ( s : & str ) -> Self {
12101255 // Internally, CBMC distinguishes between the string constant, and the pointer to it.
0 commit comments