@@ -52,11 +52,15 @@ impl RewritePass for Linearizer {
52
52
let cs = rewritten_children ( ) ;
53
53
let idx = & cs[ 1 ] ;
54
54
let tup = & cs[ 0 ] ;
55
- if let Sort :: Array ( key_sort, _ , size) = check ( & orig. cs ( ) [ 0 ] ) {
55
+ if let Sort :: Array ( key_sort, val_sort , size) = check ( & orig. cs ( ) [ 0 ] ) {
56
56
assert ! ( size > 0 ) ;
57
57
if idx. is_const ( ) {
58
58
let idx_usize = extras:: as_uint_constant ( idx) . unwrap ( ) . to_usize ( ) . unwrap ( ) ;
59
- Some ( term ! [ Op :: Field ( idx_usize) ; tup. clone( ) ] )
59
+ if idx_usize < size {
60
+ Some ( term ! [ Op :: Field ( idx_usize) ; tup. clone( ) ] )
61
+ } else {
62
+ Some ( val_sort. default_term ( ) )
63
+ }
60
64
} else {
61
65
let mut fields = ( 0 ..size) . map ( |idx| term ! [ Op :: Field ( idx) ; tup. clone( ) ] ) ;
62
66
let first = fields. next ( ) . unwrap ( ) ;
@@ -77,7 +81,11 @@ impl RewritePass for Linearizer {
77
81
assert ! ( size > 0 ) ;
78
82
if idx. is_const ( ) {
79
83
let idx_usize = extras:: as_uint_constant ( idx) . unwrap ( ) . to_usize ( ) . unwrap ( ) ;
80
- Some ( term ! [ Op :: Update ( idx_usize) ; tup. clone( ) , val. clone( ) ] )
84
+ if idx_usize < size {
85
+ Some ( term ! [ Op :: Update ( idx_usize) ; tup. clone( ) , val. clone( ) ] )
86
+ } else {
87
+ Some ( tup. clone ( ) )
88
+ }
81
89
} else {
82
90
let mut updates =
83
91
( 0 ..size) . map ( |idx| term ! [ Op :: Update ( idx) ; tup. clone( ) , val. clone( ) ] ) ;
@@ -90,6 +98,35 @@ impl RewritePass for Linearizer {
90
98
unreachable ! ( )
91
99
}
92
100
}
101
+ Op :: CStore => {
102
+ let cs = rewritten_children ( ) ;
103
+ let tup = & cs[ 0 ] ;
104
+ let idx = & cs[ 1 ] ;
105
+ let val = & cs[ 2 ] ;
106
+ let cond = & cs[ 3 ] ;
107
+ if let Sort :: Array ( key_sort, _, size) = check ( & orig. cs ( ) [ 0 ] ) {
108
+ assert ! ( size > 0 ) ;
109
+ if idx. is_const ( ) {
110
+ let idx_usize = extras:: as_uint_constant ( idx) . unwrap ( ) . to_usize ( ) . unwrap ( ) ;
111
+ if idx_usize < size {
112
+ Some (
113
+ term ! [ Op :: Ite ; cond. clone( ) , term![ Op :: Update ( idx_usize) ; tup. clone( ) , val. clone( ) ] , tup. clone( ) ] ,
114
+ )
115
+ } else {
116
+ Some ( tup. clone ( ) )
117
+ }
118
+ } else {
119
+ let mut updates =
120
+ ( 0 ..size) . map ( |idx| term ! [ Op :: Update ( idx) ; tup. clone( ) , val. clone( ) ] ) ;
121
+ let first = updates. next ( ) . unwrap ( ) ;
122
+ Some ( key_sort. elems_iter ( ) . take ( size) . skip ( 1 ) . zip ( updates) . fold ( first, |acc, ( idx_c, update) | {
123
+ term ! [ Op :: Ite ; term![ AND ; term![ Op :: Eq ; idx. clone( ) , idx_c] , cond. clone( ) ] , update, acc]
124
+ } ) )
125
+ }
126
+ } else {
127
+ unreachable ! ( )
128
+ }
129
+ }
93
130
// ITEs and EQs are correctly rewritten by default.
94
131
_ => None ,
95
132
}
0 commit comments