From 967be9e750221ab2ab783f95df79bb26d290a45e Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:07:58 +0200 Subject: add: added projects --- tiger-compiler/src/object/binder.cc | 176 ++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 tiger-compiler/src/object/binder.cc (limited to 'tiger-compiler/src/object/binder.cc') 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 +#include + +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(e); + } + + template void Binder::chunk_visit(ast::Chunk& e) + { + // Shorthand. + using chunk_type = ast::Chunk; + // FIXME: Some code was deleted here (Two passes: once on headers, then on bodies). + for (auto machala : e) + { + if (dynamic_cast(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& 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& 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(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 -- cgit v1.2.3