@@ -117,28 +117,71 @@ void string_refinementt::add_instantiations()
117117 }
118118}
119119
120+ // / List the simple expressions on which the expression depends in the
121+ // / `symbol_resolve` map. A simple expression is either a symbol or a
122+ // / constant array
123+ // / \param expr: an expression
124+ static void depends_in_symbol_map (const exprt &expr, std::vector<exprt> &accu)
125+ {
126+ if (expr.id ()==ID_if)
127+ {
128+ if_exprt if_expr=to_if_expr (expr);
129+ depends_in_symbol_map (if_expr.true_case (), accu);
130+ depends_in_symbol_map (if_expr.false_case (), accu);
131+ }
132+ else if (expr.id ()==ID_struct)
133+ {
134+ string_exprt str=to_string_expr (expr);
135+ depends_in_symbol_map (str.content (), accu);
136+ }
137+ else
138+ {
139+ INVARIANT (
140+ expr.id ()==ID_symbol || expr.id ()==ID_array || expr.id ()==ID_array_of,
141+ " leaf in symbol resolve should be a symbol or a constant array" );
142+ accu.push_back (expr);
143+ }
144+ }
145+
120146// / keeps a map of symbols to expressions, such as none of the mapped values
121147// / exist as a key
122148// / \param lhs: a symbol expression
123- // / \param rhs: an expression to map it to
149+ // / \param rhs: an expression to map it to, which should be either a symbol
150+ // / a string_exprt, an array_exprt, an array_of_exprt or an
151+ // / if_exprt with branches of the previous kind
124152void string_refinementt::add_symbol_to_symbol_map (
125153 const exprt &lhs, const exprt &rhs)
126154{
127155 PRECONDITION (lhs.id ()==ID_symbol);
156+ PRECONDITION (rhs.id ()==ID_symbol ||
157+ rhs.id ()==ID_array ||
158+ rhs.id ()==ID_array_of ||
159+ rhs.id ()==ID_if ||
160+ (rhs.id ()==ID_struct &&
161+ refined_string_typet::is_refined_string_type (rhs.type ())));
128162
129163 // We insert the mapped value of the rhs, if it exists.
130164 auto it=symbol_resolve.find (rhs);
131165 const exprt &new_rhs=it!=symbol_resolve.end ()?it->second :rhs;
132-
133166 symbol_resolve[lhs]=new_rhs;
134- reverse_symbol_resolve[new_rhs].push_back (lhs);
135167
136- const std::list<exprt> &symbols_to_update_with_new_rhs (
137- reverse_symbol_resolve[lhs]);
138- for (exprt item : symbols_to_update_with_new_rhs)
168+ // List the leaves of new_rhs
169+ std::vector<exprt> leaves;
170+ depends_in_symbol_map (new_rhs, leaves);
171+
172+ const auto &symbols_to_update_with_new_rhs=reverse_symbol_resolve[lhs];
173+
174+ // We need to update all the symbols which depend on lhs
175+ for (const exprt &item : symbols_to_update_with_new_rhs)
176+ replace_expr (symbol_resolve, symbol_resolve[item]);
177+
178+ // Every time a symbol at the leaves is updated we need to update lhs
179+ // and the symbols that depend on it
180+ for (const auto &leaf : leaves)
139181 {
140- symbol_resolve[item]=new_rhs;
141- reverse_symbol_resolve[new_rhs].push_back (item);
182+ reverse_symbol_resolve[leaf].push_back (lhs);
183+ for (const exprt &item : symbols_to_update_with_new_rhs)
184+ reverse_symbol_resolve[leaf].push_back (item);
142185 }
143186}
144187
@@ -158,9 +201,6 @@ void string_refinementt::set_char_array_equality(
158201 index_exprt arraycell (rhs, from_integer (i, index_type));
159202 equal_exprt arrayeq (arraycell, rhs.operands ()[i]);
160203 add_lemma (arrayeq, false );
161- #if 0
162- generator.axioms.push_back(arrayeq);
163- #endif
164204 }
165205 }
166206 // At least for Java (as it is currently pre-processed), we need not consider
@@ -205,7 +245,8 @@ bool string_refinementt::is_char_array(const typet &type) const
205245// / add lemmas to the solver corresponding to the given equation
206246// / \param lhs: left hand side of an equality expression
207247// / \param rhs: right and side of the equality
208- // / \return false if the lemmas were added successfully, true otherwise
248+ // / \return true if the assignemnt needs to be handled by the parent class
249+ // / via `set_to`
209250bool string_refinementt::add_axioms_for_string_assigns (
210251 const exprt &lhs, const exprt &rhs)
211252{
@@ -225,8 +266,8 @@ bool string_refinementt::add_axioms_for_string_assigns(
225266 }
226267 else if (rhs.id ()==ID_if)
227268 {
228- generator. add_axioms_for_if_array (lhs, to_if_expr ( rhs) );
229- return false ;
269+ add_symbol_to_symbol_map (lhs, rhs);
270+ return true ;
230271 }
231272 else
232273 {
@@ -632,7 +673,7 @@ void string_refinementt::add_lemma(
632673// / \return an array expression or an array_of_exprt
633674exprt string_refinementt::get_array (const exprt &arr, const exprt &size) const
634675{
635- exprt arr_val=get_array (arr);
676+ exprt arr_val=simplify_expr ( get_array (arr), ns );
636677 exprt size_val=supert::get (size);
637678 size_val=simplify_expr (size_val, ns);
638679 typet char_type=arr.type ().subtype ();
@@ -1412,6 +1453,30 @@ void string_refinementt::update_index_set(const std::vector<exprt> &cur)
14121453 update_index_set (axiom);
14131454}
14141455
1456+ // / An expression representing an array of characters can be in the form of an
1457+ // / if expression for instance `cond?array1:(cond2:array2:array3)`.
1458+ // / We return all the array expressions contained in `array_expr`.
1459+ // / \param array_expr : an expression representing an array
1460+ // / \return a vector containing symbols and constant arrays contained in the
1461+ // / expression
1462+ static std::vector<exprt> sub_arrays (const exprt &array_expr)
1463+ {
1464+ if (array_expr.id ()==ID_if)
1465+ {
1466+ std::vector<exprt> res1=sub_arrays (to_if_expr (array_expr).true_case ());
1467+ std::vector<exprt> res2=sub_arrays (to_if_expr (array_expr).false_case ());
1468+ res1.insert (res1.end (), res2.begin (), res2.end ());
1469+ return res1;
1470+ }
1471+ else
1472+ {
1473+ INVARIANT (
1474+ array_expr.id ()==ID_symbol || array_expr.id ()==ID_array,
1475+ " character arrays should be symbol, constant array, or if expression" );
1476+ return std::vector<exprt>(1 , array_expr);
1477+ }
1478+ }
1479+
14151480// / add to the index set all the indices that appear in the formula and the
14161481// / upper bound minus one
14171482// / \par parameters: a string constraint
@@ -1423,17 +1488,13 @@ void string_refinementt::add_to_index_set(const exprt &s, exprt i)
14231488 mp_integer mpi;
14241489 to_integer (i, mpi);
14251490 if (mpi<0 )
1426- {
1427- debug () << " add_to_index_set : ignoring negative number " << mpi << eom;
14281491 return ;
1429- }
1430- }
1431- if (index_set[s].insert (i).second )
1432- {
1433- debug () << " adding to index set of " << from_expr (ns, " " , s)
1434- << " : " << from_expr (ns, " " , i) << eom;
1435- current_index_set[s].insert (i);
14361492 }
1493+
1494+ std::vector<exprt> subs=sub_arrays (s);
1495+ for (const auto &sub : subs)
1496+ if (index_set[sub].insert (i).second )
1497+ current_index_set[sub].insert (i);
14371498}
14381499
14391500void string_refinementt::initial_index_set (const string_constraintt &axiom)
@@ -1504,7 +1565,6 @@ void string_refinementt::update_index_set(const exprt &formula)
15041565 }
15051566}
15061567
1507-
15081568// Will be used to visit an expression and return the index used
15091569// with the given char array that contains qvar
15101570class find_index_visitort : public const_expr_visitort
0 commit comments