/** ** \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