/** ** \file desugar/desugar-visitor.cc ** \brief Implementation of desugar::DesugarVisitor. */ #include #include #include #include #include #include #include namespace desugar { DesugarVisitor::DesugarVisitor(bool desugar_for_p, bool desugar_string_cmp_p) : super_type() , desugar_for_p_(desugar_for_p) , desugar_string_cmp_p_(desugar_string_cmp_p) {} /*-----------------------------. | Desugar string comparisons. | `-----------------------------*/ void DesugarVisitor::operator()(const ast::OpExp& e) { // FIXME DONE: Some code was deleted here. // Check to see that all of the elements to operate on are strings if (dynamic_cast(e.left_get().type_get()) == nullptr || dynamic_cast(e.right_get().type_get()) == nullptr) { return super_type::operator()(e); } const auto left = recurse(e.left_get()); const auto right = recurse(e.right_get()); misc::variant res; switch (e.oper_get()) { case ast::OpExp::Oper::eq: { res = parse::parse(parse::Tweast() << "streq(" << left << ", " << right << ") = 0"); break; } case ast::OpExp::Oper::ne: { res = parse::parse(parse::Tweast() << "streq(" << left << ", " << right << ") <> 0"); break; } case ast::OpExp::Oper::lt: { res = parse::parse(parse::Tweast() << "strcmp(" << left << ", " << right << ") = -1"); break; } case ast::OpExp::Oper::le: { res = parse::parse(parse::Tweast() << "strcmp(" << left << ", " << right << ") <= 0"); break; } case ast::OpExp::Oper::gt: { res = parse::parse(parse::Tweast() << "strcmp(" << left << ", " << right << ") = 1"); break; } case ast::OpExp::Oper::ge: { res = parse::parse(parse::Tweast() << "strcmp(" << left << ", " << right << ") >= 0"); break; } default: break; } ast::Exp* final = std::get(res); result_ = final; } /*----------------------. | Desugar `for' loops. | `----------------------*/ /*<<- Desugar `for' loops as `while' loops: for i := lo to hi do body is transformed as: let var _lo := lo var _hi := hi var i := _lo in if i <= _hi then while 1 do ( body; if i = _hi then break; i := i + 1 ) end Notice that: - a `_hi' variable is introduced so that `hi' is evaluated only once; - a `_lo' variable is introduced to prevent `i' from being in the scope of `_hi'; - a first test is performed before entering the loop, so that the loop condition becomes `i < _hi' (instead of `i <= _hi'); this is done to prevent overflows on INT_MAX. ->>*/ void DesugarVisitor::operator()(const ast::ForExp& e) { // FIXME DONE: Some code was deleted here. auto var_init = recurse(e.vardec_get().init_get()); auto lim = recurse(e.hi_get()); auto body = recurse(e.body_get()); auto iterator = e.vardec_get().name_get(); auto res = parse::parse(parse::Tweast() << "let " "var _lo := " << var_init << " var _hi := " << lim << " var " << iterator << " := _lo " "in " "if " << iterator << " <= _hi then " "while 1 do " "( " << body << ";" "if " << iterator << " = _hi then " "break;" << iterator << " := " << iterator << " + 1 " ") " "end"); ast::Exp* final = std::get(res); result_ = final; } } // namespace desugar