@@ -314,170 +314,184 @@ abstract_object_pointert constants_expression_transform(
314314
315315// /////////////////////////////////////////////////////
316316// intervals expression transform
317- using interval_abstract_value_pointert = sharing_ptrt<interval_abstract_valuet>;
318-
319- static abstract_object_pointert interval_evaluate_conditional (
320- const exprt &expr,
321- const std::vector<interval_abstract_value_pointert> &interval_operands,
322- const abstract_environmentt &env,
323- const namespacet &ns);
324- static abstract_object_pointert interval_evaluate_unary_expr (
325- const exprt &expr,
326- const std::vector<interval_abstract_value_pointert> &interval_operands,
327- const abstract_environmentt &environment,
328- const namespacet &ns);
329-
330- abstract_object_pointert intervals_expression_transform (
331- const exprt &expr,
332- const std::vector<abstract_object_pointert> &operands,
333- const abstract_environmentt &environment,
334- const namespacet &ns)
317+ class interval_evaluator
335318{
336- std::size_t num_operands = expr.operands ().size ();
337- PRECONDITION (operands.size () == num_operands);
319+ public:
320+ interval_evaluator (
321+ const exprt &e,
322+ const std::vector<abstract_object_pointert> &ops,
323+ const abstract_environmentt &env,
324+ const namespacet &n)
325+ : expression(e), operands(ops), environment(env), ns(n)
326+ {
327+ PRECONDITION (expression.operands ().size () == operands.size ());
328+ }
338329
339- std::vector<sharing_ptrt<interval_abstract_valuet>> interval_operands;
330+ abstract_object_pointert operator ()() const
331+ {
332+ return transform ();
333+ }
340334
341- for (const auto &op : operands)
335+ private:
336+ using interval_abstract_value_pointert =
337+ sharing_ptrt<const interval_abstract_valuet>;
338+
339+ abstract_object_pointert transform () const
342340 {
343- auto iav = std::dynamic_pointer_cast<const interval_abstract_valuet>(op);
344- if (!iav)
341+ auto interval_operands = operands_as_intervals ();
342+ auto num_operands = interval_operands.size ();
343+
344+ if (num_operands != operands.size ())
345345 {
346- // The operand isn't an interval - if it's an integral constant we can
347- // convert it into an interval.
346+ // We could not convert all operands into intervals,
347+ // e.g. if its type is not something we can represent as an interval,
348+ // try dispatching the expression_transform under that type instead.
349+ return constants_expression_transform (
350+ expression, operands, environment, ns);
351+ }
352+
353+ if (num_operands == 0 )
354+ return environment.abstract_object_factory (
355+ expression.type (), ns, true , false );
356+
357+ if (expression.id () == ID_if)
358+ return interval_evaluate_conditional (interval_operands);
359+
360+ if (num_operands == 1 )
361+ return interval_evaluate_unary_expr (interval_operands);
362+
363+ constant_interval_exprt result = interval_operands[0 ]->to_interval ();
348364
349- if (constant_interval_exprt::is_int (op->type ()))
365+ for (size_t opIndex = 1 ; opIndex != interval_operands.size (); ++opIndex)
366+ {
367+ auto &interval_next = interval_operands[opIndex]->to_interval ();
368+ result = result.eval (expression.id (), interval_next);
369+ }
370+
371+ INVARIANT (
372+ result.type () == expression.type (),
373+ " Type of result interval should match expression type" );
374+ return make_interval (expression.type (), result);
375+ }
376+
377+ std::vector<interval_abstract_value_pointert> operands_as_intervals () const
378+ {
379+ std::vector<interval_abstract_value_pointert> interval_operands;
380+
381+ for (const auto &op : operands)
382+ {
383+ auto iav = std::dynamic_pointer_cast<const interval_abstract_valuet>(op);
384+ if (!iav)
350385 {
351- const auto op_as_constant = op->to_constant ();
352- if (op_as_constant.is_nil ())
353- {
354- auto top_object =
355- environment.abstract_object_factory (expr.type (), ns, true , false );
356- auto top_context_object =
357- std::dynamic_pointer_cast<const context_abstract_objectt>(
358- top_object);
359- CHECK_RETURN (top_context_object);
360- return top_context_object->get_child ();
361- }
362- const auto ivop =
363- environment.abstract_object_factory (op->type (), op_as_constant, ns);
364- const auto ivop_context =
365- std::dynamic_pointer_cast<const context_abstract_objectt>(ivop);
366- if (ivop_context)
386+ // The operand isn't an interval - if it's an integral constant we can
387+ // convert it into an interval.
388+ if (constant_interval_exprt::is_int (op->type ()))
367389 {
368- iav = std::dynamic_pointer_cast<const interval_abstract_valuet>(
369- ivop_context->get_child ());
390+ const auto op_as_constant = op->to_constant ();
391+ if (op_as_constant.is_nil ())
392+ return std::vector<interval_abstract_value_pointert>();
393+
394+ const auto ivop =
395+ environment.abstract_object_factory (op->type (), op_as_constant, ns);
396+ const auto ivop_context =
397+ std::dynamic_pointer_cast<const context_abstract_objectt>(ivop);
398+ if (ivop_context)
399+ {
400+ iav = std::dynamic_pointer_cast<const interval_abstract_valuet>(
401+ ivop_context->get_child ());
402+ }
403+ else
404+ iav =
405+ std::dynamic_pointer_cast<const interval_abstract_valuet>(ivop);
370406 }
371- else
372- iav = std::dynamic_pointer_cast<const interval_abstract_valuet>(ivop );
407+ CHECK_RETURN (
408+ ! std::dynamic_pointer_cast<const context_abstract_objectt>(iav) );
373409 }
374- CHECK_RETURN (
375- !std::dynamic_pointer_cast<const context_abstract_objectt>(iav));
376410
377- if (!iav)
378- {
379- // If we could not convert the operand into an interval,
380- // e.g. if its type is not something we can represent as an interval,
381- // try dispatching the expression_transform under that type instead.
382- if (
383- std::dynamic_pointer_cast<const constant_abstract_valuet>(op) !=
384- nullptr )
385- return constants_expression_transform (
386- expr, operands, environment, ns);
387- return op->expression_transform (expr, operands, environment, ns);
388- }
411+ if (iav)
412+ interval_operands.push_back (iav);
389413 }
390414
391- INVARIANT (iav, " Should be an interval abstract value" );
392- interval_operands.push_back (iav);
415+ return interval_operands;
393416 }
394417
395- if (num_operands == 0 )
396- return environment.abstract_object_factory (expr.type (), ns, true , false );
418+ abstract_object_pointert interval_evaluate_conditional (
419+ const std::vector<interval_abstract_value_pointert> &interval_operands)
420+ const
421+ {
422+ auto const &condition_interval = interval_operands[0 ]->to_interval ();
423+ auto const &true_interval = interval_operands[1 ]->to_interval ();
424+ auto const &false_interval = interval_operands[2 ]->to_interval ();
397425
398- if (expr.id () == ID_if)
399- return interval_evaluate_conditional (
400- expr, interval_operands, environment, ns);
426+ auto condition_result = condition_interval.is_definitely_true ();
401427
402- if (num_operands == 1 )
403- return interval_evaluate_unary_expr (
404- expr, interval_operands, environment, ns);
428+ if (condition_result.is_unknown ())
429+ {
430+ // Value of the condition is both true and false, so
431+ // combine the intervals of both the true and false expressions
432+ return make_interval (
433+ expression.type (),
434+ constant_interval_exprt (
435+ constant_interval_exprt::get_min (
436+ true_interval.get_lower (), false_interval.get_lower ()),
437+ constant_interval_exprt::get_max (
438+ true_interval.get_upper (), false_interval.get_upper ())));
439+ }
405440
406- constant_interval_exprt result = interval_operands[0 ]->to_interval ();
441+ return condition_result.is_true ()
442+ ? make_interval (true_interval.type (), true_interval)
443+ : make_interval (false_interval.type (), false_interval);
444+ }
407445
408- for (size_t opIndex = 1 ; opIndex != interval_operands.size (); ++opIndex)
446+ abstract_object_pointert interval_evaluate_unary_expr (
447+ const std::vector<interval_abstract_value_pointert> &interval_operands)
448+ const
409449 {
410- auto &interval_next = interval_operands[opIndex]->to_interval ();
411- result = result.eval (expr.id (), interval_next);
412- }
450+ const constant_interval_exprt &operand_expr =
451+ interval_operands[0 ]->to_interval ();
413452
414- INVARIANT (
415- result.type () == expr.type (),
416- " Type of result interval should match expression type" );
417- return environment.abstract_object_factory (expr.type (), result, ns);
418- }
453+ if (expression.id () == ID_typecast)
454+ {
455+ const typecast_exprt &tce = to_typecast_expr (expression);
419456
420- abstract_object_pointert interval_evaluate_conditional (
421- const exprt &expr,
422- const std::vector<interval_abstract_value_pointert> &interval_operands,
423- const abstract_environmentt &env,
424- const namespacet &ns)
425- {
426- auto const &condition_interval = interval_operands[ 0 ]-> to_interval ();
427- auto const &true_interval = interval_operands[ 1 ]-> to_interval ( );
428- auto const &false_interval = interval_operands[ 2 ]-> to_interval ();
457+ const constant_interval_exprt &new_interval =
458+ operand_expr. typecast (tce. type ());
459+
460+ INVARIANT (
461+ new_interval. type () == expression. type (),
462+ " Type of result interval should match expression type " );
463+
464+ return make_interval (tce. type (), new_interval );
465+ }
429466
430- auto condition_result = condition_interval.is_definitely_true ();
467+ const constant_interval_exprt &interval_result =
468+ operand_expr.eval (expression.id ());
469+ INVARIANT (
470+ interval_result.type () == expression.type (),
471+ " Type of result interval should match expression type" );
472+ return make_interval (expression.type (), interval_result);
473+ }
431474
432- if (condition_result.is_unknown ())
475+ abstract_object_pointert
476+ make_interval (const typet &type, const exprt &expr) const
433477 {
434- // Value of the condition is both true and false, so
435- // combine the intervals of both the true and false expressions
436- return env.abstract_object_factory (
437- expr.type (),
438- constant_interval_exprt (
439- constant_interval_exprt::get_min (
440- true_interval.get_lower (), false_interval.get_lower ()),
441- constant_interval_exprt::get_max (
442- true_interval.get_upper (), false_interval.get_upper ())),
443- ns);
478+ return environment.abstract_object_factory (type, expr, ns);
444479 }
445480
446- return condition_result.is_true ()
447- ? env.abstract_object_factory (
448- true_interval.type (), true_interval, ns)
449- : env.abstract_object_factory (
450- false_interval.type (), false_interval, ns);
451- }
481+ const exprt &expression;
482+ const std::vector<abstract_object_pointert> &operands;
483+ const abstract_environmentt &environment;
484+ const namespacet &ns;
485+ };
452486
453- abstract_object_pointert interval_evaluate_unary_expr (
487+ abstract_object_pointert intervals_expression_transform (
454488 const exprt &expr,
455- const std::vector<interval_abstract_value_pointert > &interval_operands ,
489+ const std::vector<abstract_object_pointert > &operands ,
456490 const abstract_environmentt &environment,
457491 const namespacet &ns)
458492{
459- const constant_interval_exprt &operand_expr =
460- interval_operands[0 ]->to_interval ();
461-
462- if (expr.id () == ID_typecast)
463- {
464- const typecast_exprt &tce = to_typecast_expr (expr);
465-
466- const constant_interval_exprt &new_interval =
467- operand_expr.typecast (tce.type ());
468-
469- INVARIANT (
470- new_interval.type () == expr.type (),
471- " Type of result interval should match expression type" );
472-
473- return environment.abstract_object_factory (tce.type (), new_interval, ns);
474- }
475-
476- const constant_interval_exprt &interval_result = operand_expr.eval (expr.id ());
477- INVARIANT (
478- interval_result.type () == expr.type (),
479- " Type of result interval should match expression type" );
480- return environment.abstract_object_factory (expr.type (), interval_result, ns);
493+ auto evaluator = interval_evaluator (expr, operands, environment, ns);
494+ return evaluator ();
481495}
482496
483497// ///////////////////////////////////////////////////////
0 commit comments