recognize dotimes (#310)

This commit is contained in:
water111
2021-03-05 21:46:39 -05:00
committed by GitHub
parent 65ffe83468
commit b352dcefa9
10 changed files with 408 additions and 337 deletions
+70
View File
@@ -1969,4 +1969,74 @@ void LetElement::set_body(Form* new_body) {
m_body->parent_element = this;
}
/////////////////////////////
// DoTimesElement
/////////////////////////////
DoTimesElement::DoTimesElement(RegisterAccess var_init,
RegisterAccess var_check,
RegisterAccess var_inc,
Form* check_value,
Form* body)
: m_var_init(var_init),
m_var_check(var_check),
m_var_inc(var_inc),
m_check_value(check_value),
m_body(body) {
m_body->parent_element = this;
m_check_value->parent_element = this;
assert(m_var_inc.reg() == m_var_check.reg());
assert(m_var_init.reg() == m_var_inc.reg());
}
goos::Object DoTimesElement::to_form_internal(const Env& env) const {
std::vector<goos::Object> outer = {
pretty_print::to_symbol("dotimes"),
pretty_print::build_list(m_var_init.to_form(env), m_check_value->to_form(env))};
m_body->inline_forms(outer, env);
return pretty_print::build_list(outer);
}
void DoTimesElement::apply(const std::function<void(FormElement*)>& f) {
f(this);
m_check_value->apply(f);
m_body->apply(f);
}
void DoTimesElement::apply_form(const std::function<void(Form*)>& f) {
m_check_value->apply_form(f);
m_body->apply_form(f);
}
void DoTimesElement::collect_vars(RegAccessSet& vars, bool recursive) const {
vars.insert(m_var_init);
vars.insert(m_var_check);
vars.insert(m_var_inc);
if (recursive) {
m_body->collect_vars(vars, recursive);
m_check_value->collect_vars(vars, recursive);
}
}
void DoTimesElement::get_modified_regs(RegSet& regs) const {
regs.insert(m_var_inc.reg());
m_body->get_modified_regs(regs);
m_check_value->get_modified_regs(regs);
}
std::optional<SimpleAtom> form_as_atom(const Form* f) {
auto as_single = f->try_as_single_element();
auto as_atom = dynamic_cast<SimpleAtomElement*>(as_single);
if (as_atom) {
return as_atom->atom();
}
auto as_se = dynamic_cast<SimpleExpressionElement*>(as_single);
if (as_se && as_se->expr().is_identity()) {
return as_se->expr().get_arg(0);
}
return {};
}
} // namespace decompiler