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/object/binder.cc | |
Diffstat (limited to 'tiger-compiler/src/object/binder.cc')
| -rw-r--r-- | tiger-compiler/src/object/binder.cc | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tiger-compiler/src/object/binder.cc b/tiger-compiler/src/object/binder.cc new file mode 100644 index 0000000..8220da5 --- /dev/null +++ b/tiger-compiler/src/object/binder.cc @@ -0,0 +1,176 @@ +/** + ** \file object/binder.cc + ** \brief Implementation of object::Binder. + */ + +#include <ast/all.hh> +#include <object/binder.hh> + +namespace object +{ + /*---------. + | Visits. | + `---------*/ + + /* Handle the case of `self'. If the variable is not named `self', handle it + like the normal `Binder'. If it is `self', it must be bound to a definiton + site, unless: + * it is inside a method, + * AND `self` is not overridden. + If those conditions are met, `self' is an implicitly defined instance of + the class. + + Variable `self' will have a meaningful definition after the object + constructs have been desugared. */ + + void Binder::operator()(ast::SimpleVar& e) + { + // FIXME DONE: Some code was deleted here. + misc::symbol test_self("self"); + if (e.name_get() == test_self && within_method_dec_ && !overrided_self_) + { + e.def_set(nullptr); + } + else + { + super_type::operator()(e); + } + } + + // Handle the case of `Object'. + void Binder::operator()(ast::NameTy& e) + { + // FIXME DONE: Some code was deleted here. + misc::symbol test_obj("Object"); + if (e.name_get() == test_obj) + { + e.def_set(nullptr); + } + else + { + super_type::operator()(e); + } + } + + /*---------------. + | Visiting Exp. | + `---------------*/ + + void Binder::operator()(ast::ForExp& e) + { + bool saved_within_class_ty = within_class_ty_; + within_class_ty_ = false; + super_type::operator()(e); + within_class_ty_ = saved_within_class_ty; + } + + /*-------------------. + | Visiting ClassTy. | + `-------------------*/ + + void Binder::operator()(ast::ClassTy& e) + { + // FIXME DONE: Some code was deleted here (Scope begins). + begin_scope(); + e.super_get().accept(*this); + bool saved_within_class_ty = within_class_ty_; + within_class_ty_ = true; + bool saved_within_method_dec = within_method_dec_; + within_method_dec_ = false; + e.chunks_get().accept(*this); + within_method_dec_ = saved_within_method_dec; + within_class_ty_ = saved_within_class_ty; + // FIXME DONE: Some code was deleted here (Scope ends). + end_scope(); + } + + /*---------------. + | Visiting Dec. | + `---------------*/ + + void Binder::operator()(ast::VarDec& e) + { + if (within_class_ty_) + { + within_class_ty_ = false; + // Don't bind class attributes. + super_type::super_type::operator()(e); + within_class_ty_ = true; + } + else + { + // But still bind other variable declarations. + super_type::operator()(e); + if (e.name_get() == "self" && within_method_dec_) + overrided_self_ = true; + } + } + + void Binder::operator()(ast::FunctionChunk& e) + { + chunk_visit<ast::FunctionDec>(e); + } + + template <class D> void Binder::chunk_visit(ast::Chunk<D>& e) + { + // Shorthand. + using chunk_type = ast::Chunk<D>; + // FIXME: Some code was deleted here (Two passes: once on headers, then on bodies). + for (auto machala : e) + { + if (dynamic_cast<ast::MethodDec*>(machala)) + { + scoped_map_fun_.put(machala->name_get(), machala); + } + } + super_type::operator()(e); + } + + // This trampoline is needed, since `virtual' and `template' cannot + // be mixed. + template <> + void Binder::visit_dec_header<ast::FunctionDec>(ast::FunctionDec& e) + { + // FIXME DONE: Some code was deleted here (Call the super type). + super_type::operator()(e); + } + + // Compute the bindings of this function's body. + template <> void Binder::visit_dec_body<ast::FunctionDec>(ast::FunctionDec& e) + { + bool saved_within_class_ty = within_class_ty_; + within_class_ty_ = false; + bool saved_within_method_dec = within_method_dec_; + within_method_dec_ = false; + // FIXME DONE: Some code was deleted here (Call the super type). + super_type::operator()(e); + within_method_dec_ = saved_within_method_dec; + within_class_ty_ = saved_within_class_ty; + } + + /* We can't bind methods definitions without types, so we don't + store them. Nonetheless, object::Binder must still recurse + through the children of ast::MethodChunk to bind other names. + + Note that as we defer the binding of methods to the + type-checkimg, there is no need to visit method in two-pass (like + bind::Binder does for functions for instance). */ + void Binder::operator()(ast::MethodDec& e) + { + // FIXME DONE: Some code was deleted here (Scope begins). + begin_scope(); + bool saved_within_class_ty = within_class_ty_; + within_class_ty_ = false; + bool saved_within_method_dec = within_method_dec_; + within_method_dec_ = true; + bool saved_overrided_self = overrided_self_; + overrided_self_ = false; + ast::DefaultVisitor::operator()(static_cast<ast::FunctionDec&>(e)); + within_method_dec_ = saved_within_method_dec; + within_class_ty_ = saved_within_class_ty; + overrided_self_ = saved_overrided_self; + // FIXME DONE: Some code was deleted here (Scope ends). + end_scope(); + } + +} // namespace object |
