diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/desugar/desugar-visitor.cc | |
Diffstat (limited to 'tiger-compiler/src/desugar/desugar-visitor.cc')
| -rw-r--r-- | tiger-compiler/src/desugar/desugar-visitor.cc | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/tiger-compiler/src/desugar/desugar-visitor.cc b/tiger-compiler/src/desugar/desugar-visitor.cc new file mode 100644 index 0000000..770cdf6 --- /dev/null +++ b/tiger-compiler/src/desugar/desugar-visitor.cc @@ -0,0 +1,144 @@ +/** + ** \file desugar/desugar-visitor.cc + ** \brief Implementation of desugar::DesugarVisitor. + */ + +#include <ast/all.hh> +#include <ast/libast.hh> +#include <desugar/desugar-visitor.hh> +#include <misc/algorithm.hh> +#include <misc/symbol.hh> +#include <parse/libparse.hh> +#include <parse/tweast.hh> + +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<const type::String*>(e.left_get().type_get()) == nullptr + || dynamic_cast<const type::String*>(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<ast::Exp*, ast::ChunkList*> 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<ast::Exp*>(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<ast::Exp*>(res); + result_ = final; + } + +} // namespace desugar |
