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/bind/binder.cc | 183 ++++++++++++++++++++++++++++++++++++ tiger-compiler/src/bind/binder.hh | 138 +++++++++++++++++++++++++++ tiger-compiler/src/bind/binder.hxx | 124 ++++++++++++++++++++++++ tiger-compiler/src/bind/libbind.cc | 31 ++++++ tiger-compiler/src/bind/libbind.hh | 29 ++++++ tiger-compiler/src/bind/local.am | 17 ++++ tiger-compiler/src/bind/renamer.cc | 63 +++++++++++++ tiger-compiler/src/bind/renamer.hh | 62 ++++++++++++ tiger-compiler/src/bind/renamer.hxx | 24 +++++ tiger-compiler/src/bind/tasks.cc | 34 +++++++ tiger-compiler/src/bind/tasks.hh | 42 +++++++++ 11 files changed, 747 insertions(+) create mode 100644 tiger-compiler/src/bind/binder.cc create mode 100644 tiger-compiler/src/bind/binder.hh create mode 100644 tiger-compiler/src/bind/binder.hxx create mode 100644 tiger-compiler/src/bind/libbind.cc create mode 100644 tiger-compiler/src/bind/libbind.hh create mode 100644 tiger-compiler/src/bind/local.am create mode 100644 tiger-compiler/src/bind/renamer.cc create mode 100644 tiger-compiler/src/bind/renamer.hh create mode 100644 tiger-compiler/src/bind/renamer.hxx create mode 100644 tiger-compiler/src/bind/tasks.cc create mode 100644 tiger-compiler/src/bind/tasks.hh (limited to 'tiger-compiler/src/bind') diff --git a/tiger-compiler/src/bind/binder.cc b/tiger-compiler/src/bind/binder.cc new file mode 100644 index 0000000..171e199 --- /dev/null +++ b/tiger-compiler/src/bind/binder.cc @@ -0,0 +1,183 @@ +/** + ** \file bind/binder.cc + ** \brief Implementation for bind/binder.hh. + */ + +#include +#include + +#include + +namespace bind +{ + /*-----------------. + | Error handling. | + `-----------------*/ + + /// The error handler. + const misc::error& Binder::error_get() const { return error_; } + + // FIXME DONE: Some code was deleted here. + void Binder::operator()(ast::SimpleVar& e) + { + ast::VarDec* init = scoped_map_var_.get(e.name_get()); + if (init == nullptr) + { + err_undef(e.location_get(), e.name_get()); + return; + } + e.def_set(init); + } + + void Binder::operator()(ast::CallExp& e) + { + ast::FunctionDec* init = scoped_map_fun_.get(e.name_get()); + if (init == nullptr) + { + err_undef(e.location_get(), e.name_get()); + return; + } + e.def_set(init); + super_type::operator()(e); + } + + void Binder::operator()(ast::NameTy& e) + { + misc::symbol test_string("string"); + misc::symbol test_int("int"); + if (e.name_get() == test_int || e.name_get() == test_string) + { + auto init = scoped_map_ty_.get(e.name_get()); + e.def_set(init); + } + else + { + auto init = scoped_map_ty_.get(e.name_get()); + if (init == nullptr) + { + err_type_undef(e.location_get(), e.name_get()); + return; + } + e.def_set(init); + } + } + + void Binder::operator()(ast::WhileExp& e) + { + bool actual = in_a_while_; + e.test_get().accept(*this); + loop_.emplace_back(&e); + in_a_while_ = true; + begin_scope(); + e.body_get().accept(*this); + end_scope(); + loop_.pop_back(); + in_a_while_ = actual; + } + + void Binder::operator()(ast::ForExp& e) + { + bool actual = in_a_while_; + begin_scope(); + in_a_while_ = true; + e.vardec_get().accept(*this); + e.hi_get().accept(*this); + loop_.emplace_back(&e); + e.body_get().accept(*this); + end_scope(); + loop_.pop_back(); + in_a_while_ = actual; + } + + void Binder::operator()(ast::BreakExp& e) + { + if (loop_.empty() || !in_a_while_) + { + error_ << misc::error::error_type::bind; + error_ << e.location_get() << ": 'break' outside any loop\n"; + } + else + { + e.def_set(loop_.back()); + } + } + + //Declaration of function + + void Binder::operator()(ast::VarDec& e) + { + bool actual = in_a_while_; + scoped_map_var_.put(e.name_get(), &e); + in_a_while_ = false; + super_type::operator()(e); + in_a_while_ = actual; + } + + void Binder::operator()(ast::FunctionChunk& e) + { + chunk_visit(e); + } + + void Binder::operator()(ast::TypeChunk& e) + { + chunk_visit(e); + } + + template void Binder::chunk_visit(ast::Chunk& e) + { + misc::scoped_map def = misc::scoped_map(); + for (auto machala : e) + { + visit_dec_head(*machala); + } + for (auto dec : e) + { + auto init = def.get(dec->name_get()); + if (init == nullptr) + { + def.put(dec->name_get(), dec); + visit_dec_bod(*dec); + } + else + { + err_ddec(dec->location_get(), init->location_get(), dec->name_get()); + } + } + } + + void Binder::operator()(ast::FunctionDec& e) + { + if (e.name_get() == "_main") + { + if (is_main_already_) + { + error_ << misc::error::error_type::bind; + error_ << "Un deuxieme _main??????\n"; + return; + } + is_main_already_ = true; + if (in_a_scope_) + { + error_ << misc::error::error_type::bind; + error_ << "BRADDOCK, je vous préviens, attention ou vous mettez votre _main!!"; + return; + } + } + scoped_map_fun_.put(e.name_get(), &e); + bool scope = in_a_scope_; + bool actual = in_a_while_; + in_a_while_ = false; + in_a_scope_ = true; + this->accept(e.result_get()); + body_func(e); + in_a_while_ = actual; + in_a_scope_ = scope; + } + + void Binder::operator()(ast::TypeDec& e) + { + scoped_map_ty_.put(e.name_get(), &e); + super_type::operator()(e); + } + +} // namespace bind diff --git a/tiger-compiler/src/bind/binder.hh b/tiger-compiler/src/bind/binder.hh new file mode 100644 index 0000000..f5a4ab3 --- /dev/null +++ b/tiger-compiler/src/bind/binder.hh @@ -0,0 +1,138 @@ +/** + ** \file bind/binder.hh + ** \brief Declaration of bind::Binder. + **/ + +#pragma once + +#include + +#include +#include +#include + +#include +#include +#include + +namespace bind +{ + /** \brief Binding identifier uses to their definitions. + ** + ** When the \c Binder finds a declaration (of a variable/formal, function, + ** or type), it keeps a pointer to it. When it finds a use, it binds it + ** to its definition, i.e., it annotates it with a pointer to the + ** declaration. + ** + ** The \c Binder diagnoses identifier use errors (invalid multiple + ** definitions, unbound identifiers etc.). + ** + ** Since identifier bindings depend on scopes, it needs an environment. + ** + ** In the original Tiger by A. Appel, there are two namespaces: on + ** the one hand types, and on the other hand functions and variables. + ** Here, at EPITA, we will use three name spaces: we will allow + ** variables and functions with the same name. + ** + ** Moreover, object constructs make use of two additional name + ** spaces: one for class attributes and one for methods (actually + ** these two name spaces only live within the scope of a class). + ** + ** Note that this Binder is mainly doing nothing: it is just + ** interested in declarations and uses. To avoid writing + ** all the methods that `do nothing but walk', it derives + ** from \c ast::DefaultVisitor. + **/ + class Binder + : public ast::DefaultVisitor + , public ast::ObjectVisitor + , public ast::AssertVisitor + { + public: + /// Super class type. + using super_type = ast::DefaultVisitor; + /// Import all the overloaded \c operator() methods. + using super_type::operator(); + + /// The error handler. + const misc::error& error_get() const; + + // FIXME DONE: Some code was deleted here. + + void operator()(ast::SimpleVar& e) override; + void operator()(ast::CallExp& e) override; + void operator()(ast::WhileExp& e) override; + void operator()(ast::ForExp& e) override; + void operator()(ast::BreakExp&) override; + void operator()(ast::NameTy& e) override; + + // ---------------- // + // Visiting /Dec/. // + // ---------------- // + + /// Visit Var declarations. + void operator()(ast::VarDec& e) override; + + /// Visit Chunk + template void chunk_visit(ast::Chunk& e); + + /// Visit Function declarations. + void operator()(ast::FunctionChunk& e) override; + void operator()(ast::FunctionDec& e) override; + /// Visit Type declarations. + void operator()(ast::TypeChunk& e) override; + void operator()(ast::TypeDec& e) override; + + Binder(); + + + /// \name Type and Function declarations + /// \{ + + /// When traversing a function (or a type) we both have to bind + /// its body (i.e., we need to enter a new scope and push the + /// arguments in it), *and* we have to store the function's + /// declaration in the current scope (so that other functions can + /// call it). + + /// We first introduce the function's name in the outer + /// environment so that the function can call itself recursively. + /// In the mean time, we also check for uniqueness. Then, as a + /// second step, we process the contents of all the functions + /// belonging to the current chunk. + + // FIXME DONE: Some code was deleted here. + //function a effect sur les scoped map + void body_func(ast::FunctionDec& e); + void begin_scope(); + void end_scope(); + template void visit_dec_bod(D& e); + template void visit_dec_head(D& e); + + + //function that handles error + void err_undef(const ast::Location& loc, const misc::symbol& name); + void err_type_undef(const ast::Location& loc, const misc::symbol& name); + void err_ddec(const ast::Location& loc, + const ast::Location& first, + const misc::symbol& name); + void is_there__main(void); + + protected: + /// Binding errors handler. + misc::error error_; + + // FIXME DONE: Some code was deleted here (More members). + // J'ai copier pretty print en sah + template using t = typename Type::type; + misc::scoped_map scoped_map_var_; + misc::scoped_map scoped_map_ty_; + misc::scoped_map scoped_map_fun_; + std::vector loop_; + bool is_main_already_ = false; + bool in_a_while_ = false; + bool in_a_scope_ = false; + }; +} // namespace bind + +#include diff --git a/tiger-compiler/src/bind/binder.hxx b/tiger-compiler/src/bind/binder.hxx new file mode 100644 index 0000000..0facad9 --- /dev/null +++ b/tiger-compiler/src/bind/binder.hxx @@ -0,0 +1,124 @@ +/** + ** \file bind/binder.hxx + ** \brief Inline methods of bind::Binder. + **/ + +// FIXME DONE: Some code was deleted here. + +#pragma once + +#include + +namespace bind +{ + inline Binder::Binder() + { + scoped_map_fun_ = misc::scoped_map(); + scoped_map_var_ = misc::scoped_map(); + scoped_map_ty_ = misc::scoped_map(); + loop_ = std::vector(); + error_ = misc::error(); + } + + inline void Binder::body_func(ast::FunctionDec& e) + { + begin_scope(); + bool tmp = in_a_scope_; + in_a_scope_ = true; + e.formals_get().accept(*this); + this->accept(e.body_get()); + in_a_scope_ = tmp; + end_scope(); + } + + template <> + inline void Binder::visit_dec_head(ast::FunctionDec& e) + { + if (e.name_get() == "_main") + { + if (is_main_already_) + { + error_ << misc::error::error_type::bind; + error_ << "Un deuxieme _main??????\n"; + return; + } + is_main_already_ = true; + if (in_a_scope_) + { + error_ << misc::error::error_type::bind; + error_ << "BRADDOCK, je vous préviens, attention ou vous mettez votre _main!!"; + return; + } + } + scoped_map_fun_.put(e.name_get(), &e); + } + + template <> + inline void Binder::visit_dec_bod(ast::FunctionDec& e) + { + bool actual = in_a_while_; + in_a_while_ = false; + this->accept(e.result_get()); + body_func(e); + in_a_while_ = actual; + } + + /// @brief visit header so the Ast can know this type exist + /// @param e an Dec of a funcrion or ast + template <> + inline void Binder::visit_dec_head(ast::TypeDec& e) + { + scoped_map_ty_.put(e.name_get(), &e); + } + + template <> + inline void Binder::visit_dec_bod(ast::TypeDec& e) + { + super_type::operator()(e); + } + + inline void Binder::begin_scope() + { + scoped_map_fun_.scope_begin(); + scoped_map_ty_.scope_begin(); + scoped_map_var_.scope_begin(); + } + + inline void Binder::end_scope() + { + scoped_map_fun_.scope_end(); + scoped_map_ty_.scope_end(); + scoped_map_var_.scope_end(); + } + + inline void Binder::err_undef(const ast::Location& loc, const misc::symbol& name) + { + error_ << misc::error::error_type::bind; + error_ << loc << ": undeclared variable: " << name << "\n"; + } + + inline void Binder::err_type_undef(const ast::Location& loc, const misc::symbol& name) + { + error_ << misc::error::error_type::bind; + error_ << loc << ": undeclared type: " << name << "\n"; + } + + inline void Binder::is_there__main() + { + if (!is_main_already_) + { + error_ << misc::error::error_type::bind; + error_ << "Bah bro il est ou ton _main??????\n"; + } + } + + inline void Binder::err_ddec(const ast::Location& loc, + const ast::Location& first, + const misc::symbol& name) + { + error_ << misc::error::error_type::bind; + error_ << loc << ": redefinition: " << name << "\n"; + error_ << first << ": first definition\n"; + } + +} // namespace bind \ No newline at end of file diff --git a/tiger-compiler/src/bind/libbind.cc b/tiger-compiler/src/bind/libbind.cc new file mode 100644 index 0000000..63dc4ee --- /dev/null +++ b/tiger-compiler/src/bind/libbind.cc @@ -0,0 +1,31 @@ +/** + ** \file bind/libbind.cc + ** \brief Define exported bind functions. + */ + + +// FIXME DONE: Some code was deleted here. + +#include +#include + +#include "renamer.hh" +#include "binder.hh" + +namespace bind +{ + misc::error bind(ast::ChunkList* d) + { + Binder bdc = Binder(); + bdc(d); + bdc.is_there__main(); + return bdc.error_get(); + } + + misc::error rename(ast::Ast& tree) + { + Renamer renamer; + renamer(tree); + return misc::error{}; + } +} diff --git a/tiger-compiler/src/bind/libbind.hh b/tiger-compiler/src/bind/libbind.hh new file mode 100644 index 0000000..f4b8bb5 --- /dev/null +++ b/tiger-compiler/src/bind/libbind.hh @@ -0,0 +1,29 @@ +/** +** \file bind/libbind.hh + ** \brief Interface of the bind module. + */ + +// FIXME DONE: Some code was deleted here. + +#pragma once + +#include +#include +#include + +namespace bind +{ + /// \brief Bind the whole ast in place, return the error code + /// + /// \param last the ast you want to bind + /// + /// \return a misc::error that serve to indicate possible failure + misc::error bind(ast::ChunkList* d); + + /// \brief Rename the whole ast in place + /// + /// \param ast the ast you want to rename + /// + /// \return a misc::error that serve to indicate possible failure + misc::error rename(ast::Ast& ast); +} // namespace bind diff --git a/tiger-compiler/src/bind/local.am b/tiger-compiler/src/bind/local.am new file mode 100644 index 0000000..ae4d7b4 --- /dev/null +++ b/tiger-compiler/src/bind/local.am @@ -0,0 +1,17 @@ +## bind module. + +src_libtc_la_SOURCES += \ + %D%/binder.hh %D%/binder.hxx %D%/binder.cc \ + %D%/libbind.hh %D%/libbind.cc +src_libtc_la_SOURCES += \ + %D%/renamer.hh %D%/renamer.hxx %D%/renamer.cc + + +TASKS += %D%/tasks.hh %D%/tasks.cc + +## ------- ## +## Tests. ## +## ------- ## + +check_PROGRAMS += %D%/test-bind +%C%_test_bind_LDADD = src/libtc.la diff --git a/tiger-compiler/src/bind/renamer.cc b/tiger-compiler/src/bind/renamer.cc new file mode 100644 index 0000000..1f13de0 --- /dev/null +++ b/tiger-compiler/src/bind/renamer.cc @@ -0,0 +1,63 @@ +/** + ** \file bind/renamer.cc + ** \brief Implementation of bind::Renamer. + */ + +#include + +namespace bind +{ + using namespace ast; + + // FIXME DONE: Some code was deleted here. + + void Renamer::operator()(ast::VarDec& e) + { + if (renames_.find(&e) != renames_.end()) + super_type::operator()(e); + new_name_(&e); + e.name_set(renames_.at(&e)); + super_type::operator()(e); + } + void Renamer::operator()(ast::TypeDec& e) + { + if (renames_.find(&e) != renames_.end()) + super_type::operator()(e); + new_name_(&e); + e.name_set(renames_.at(&e)); + super_type::operator()(e); + } + void Renamer::operator()(ast::FunctionDec& e) + { + if (e.body_get() == nullptr || e.name_get() == "_main" + || renames_.find(&e) != renames_.end()) + { + super_type::operator()(e); + return; + } + new_name_(&e); + e.name_set(renames_.at(&e)); + super_type::operator()(e); + } + void Renamer::operator()(ast::SimpleVar& e) + { + if (renames_.find(e.def_get()) != renames_.end()) + e.name_set(renames_.at(e.def_get())); + } + void Renamer::operator()(ast::NameTy& e) + { + if (renames_.find(e.def_get()) != renames_.end()) + e.name_set(renames_.at(e.def_get())); + } + void Renamer::operator()(ast::CallExp& e) + { + if (e.def_get() == nullptr || e.def_get()->body_get() == nullptr + || e.name_get() == "_main") + super_type::operator()(e); + else + { + e.name_set(renames_.at(e.def_get())); + super_type::operator()(e); + } + } +} // namespace bind diff --git a/tiger-compiler/src/bind/renamer.hh b/tiger-compiler/src/bind/renamer.hh new file mode 100644 index 0000000..f4a1e82 --- /dev/null +++ b/tiger-compiler/src/bind/renamer.hh @@ -0,0 +1,62 @@ +/** + ** \file bind/renamer.hh + ** \brief Implementation of bind::Renamer. + */ + +#pragma once + +#include +#include +#include +#include + +namespace bind +{ + /// Perform identifier renaming within an AST (in place), + /// without support for objects. + class Renamer + : public ast::DefaultVisitor + , public ast::NonObjectVisitor + , public ast::NonAssertVisitor + { + public: + using super_type = ast::DefaultVisitor; + + // Import overloaded virtual functions. + using super_type::operator(); + + // FIXME DONE: Some code was deleted here. + + // Visit methods. + /// \brief Process a declaration body or a usage site. + /// + /// \a def is the definition site of \e (must be equal to + /// \a e if it is a Dec node). + template void visit(E& e, const Def* def); + + /// \name Visiting definition sites. + /// \{ + // FIXME DONE: Some code was deleted here. + void operator()(ast::VarDec& e) override; + void operator()(ast::TypeDec& e) override; + void operator()(ast::FunctionDec& e) override; + /// \} + + /// \name Visiting usage sites. + /// \{ + // FIXME DONE: Some code was deleted here. + void operator()(ast::SimpleVar& e) override; + void operator()(ast::NameTy& e) override; + void operator()(ast::CallExp& e) override; + /// \} + + private: + // FIXME DONE: Some code was deleted here. + std::map renames_; + + void new_name_(const ast::Dec*); + }; + +} // namespace bind + +#include diff --git a/tiger-compiler/src/bind/renamer.hxx b/tiger-compiler/src/bind/renamer.hxx new file mode 100644 index 0000000..f01b7c8 --- /dev/null +++ b/tiger-compiler/src/bind/renamer.hxx @@ -0,0 +1,24 @@ +/** + ** \file bind/renamer.hxx + ** \brief Template methods of bind::Renamer. + */ + +#pragma once + +#include +#include + +namespace bind +{ + // FIXME DONE: Some code was deleted here. + inline void Renamer::new_name_(const ast::Dec* dec) + { + renames_.insert_or_assign(dec, misc::symbol::fresh(dec->name_get())); + } + + template void Renamer::visit(E& e, const Def* def) + { + // FIXME DONE: Some code was deleted here. + operator()(e); + } +} // namespace bind diff --git a/tiger-compiler/src/bind/tasks.cc b/tiger-compiler/src/bind/tasks.cc new file mode 100644 index 0000000..6492463 --- /dev/null +++ b/tiger-compiler/src/bind/tasks.cc @@ -0,0 +1,34 @@ +/** + ** \file bind/tasks.cc + ** \brief Bind module tasks implementation. + */ + +// FIXME DONE: Some code was deleted here. +#include +#include +#include +#define DEFINE_TASKS 1 +#include +#undef DEFINE_TASKS +#include + +namespace bind::tasks +{ + + void bind() { + misc::error& program_error = task_error(); + program_error << bind::bind(ast::tasks::the_program.get()); + program_error.exit_on_error(); + } + + void display_bind() { + ast::bindings_display(std::cout) = true; + } + + void rename() { + misc::error& program_error = task_error(); + program_error << bind::rename(*ast::tasks::the_program); + program_error.exit_on_error(); + } + +} diff --git a/tiger-compiler/src/bind/tasks.hh b/tiger-compiler/src/bind/tasks.hh new file mode 100644 index 0000000..5ad970d --- /dev/null +++ b/tiger-compiler/src/bind/tasks.hh @@ -0,0 +1,42 @@ +/** + ** \file bind/tasks.hh + ** \brief Bind module related tasks. + */ + +// FIXME DONE: Some code was deleted here. +#pragma once + +#include + +namespace bind::tasks +{ + TASK_GROUP("4. Binding"); + + // Binding tasks + DISJUNCTIVE_TASK_DECLARE("bound", + "default the binding to Tiger " + "(without objects nor overloading)", + "bindings-compute" + " combine-bindings-compute" + " object-bindings-compute" + " assert-bindings-compute"); + + TASK_DECLARE("b|bindings-compute", + "bind the name uses to their definitions", + bind, + "parse"); + + TASK_DECLARE("B|bindings-display", + "enable the bindings display in the next --ast-display " + "invocation. does not imply --bindings-compute", + display_bind, + ""); + + // Renaming tasks + + TASK_DECLARE("rename", + "rename identifiers", + rename, + "bindings-compute"); + +} -- cgit v1.2.3