Skip to content

adding instructiont::transform(f) #4237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/goto-programs/goto_program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,111 @@ void goto_programt::instructiont::validate(
}
}

void goto_programt::instructiont::transform(
std::function<optionalt<exprt>(exprt)> f)
{
switch(type)
{
case OTHER:
if(get_other().get_statement() == ID_expression)
{
auto new_expression = f(to_code_expression(get_other()).expression());
if(new_expression.has_value())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about
if(auto e = f(to_code_expression(get_other()).expression())) { ... }?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I would need to deviate from that pattern for assignments and function calls.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware - was just an idea, no need to actually do it.

{
auto new_other = to_code_expression(get_other());
new_other.expression() = *new_expression;
set_other(new_other);
}
}
break;

case RETURN:
{
auto new_return_value = f(get_return().return_value());
if(new_return_value.has_value())
{
auto new_return = get_return();
new_return.return_value() = *new_return_value;
set_return(new_return);
}
}
break;

case ASSIGN:
{
auto new_assign_lhs = f(get_assign().lhs());
auto new_assign_rhs = f(get_assign().rhs());
if(new_assign_lhs.has_value() || new_assign_rhs.has_value())
{
auto new_assignment = get_assign();
new_assignment.lhs() = new_assign_lhs.value_or(new_assignment.lhs());
new_assignment.rhs() = new_assign_rhs.value_or(new_assignment.rhs());
set_assign(new_assignment);
}
}
break;

case DECL:
{
auto new_symbol = f(get_decl().symbol());
if(new_symbol.has_value())
{
auto new_decl = get_decl();
new_decl.symbol() = to_symbol_expr(*new_symbol);
set_decl(new_decl);
}
}
break;

case DEAD:
{
auto new_symbol = f(get_dead().symbol());
if(new_symbol.has_value())
{
auto new_dead = get_dead();
new_dead.symbol() = to_symbol_expr(*new_symbol);
set_dead(new_dead);
}
}
break;

case FUNCTION_CALL:
{
auto new_call = get_function_call();
bool change = false;

auto new_lhs = f(new_call.lhs());
if(new_lhs.has_value())
{
new_call.lhs() = *new_lhs;
change = true;
}

for(auto &a : new_call.arguments())
{
auto new_a = f(a);
if(new_a.has_value())
{
a = *new_a;
change = true;
}
}

if(change)
set_function_call(new_call);
}
break;

default:
if(has_condition())
{
auto new_condition = f(get_condition());
if(new_condition.has_value())
set_condition(new_condition.value());
}
}
}

bool goto_programt::equals(const goto_programt &other) const
{
if(instructions.size() != other.instructions.size())
Expand Down
4 changes: 4 additions & 0 deletions src/goto-programs/goto_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,10 @@ class goto_programt
/// The validation mode indicates whether well-formedness check failures are
/// reported via DATA_INVARIANT violations or exceptions.
void validate(const namespacet &ns, const validation_modet vm) const;

/// Apply given transformer to all expressions; no return value
/// means no change needed.
void transform(std::function<optionalt<exprt>(exprt)>);
};

// Never try to change this to vector-we mutate the list while iterating
Expand Down