summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/bind/binder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tiger-compiler/src/bind/binder.cc')
-rw-r--r--tiger-compiler/src/bind/binder.cc183
1 files changed, 183 insertions, 0 deletions
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 <ast/all.hh>
+#include <bind/binder.hh>
+
+#include <misc/contract.hh>
+
+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<ast::FunctionDec>(e);
+ }
+
+ void Binder::operator()(ast::TypeChunk& e)
+ {
+ chunk_visit<ast::TypeDec>(e);
+ }
+
+ template <class D> void Binder::chunk_visit(ast::Chunk<D>& e)
+ {
+ misc::scoped_map<const misc::symbol, D*> def = misc::scoped_map<const misc::symbol, D*>();
+ for (auto machala : e)
+ {
+ visit_dec_head<D>(*machala);
+ }
+ for (auto dec : e)
+ {
+ auto init = def.get(dec->name_get());
+ if (init == nullptr)
+ {
+ def.put(dec->name_get(), dec);
+ visit_dec_bod<D>(*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