diff options
Diffstat (limited to 'tiger-compiler/src/overload')
| -rw-r--r-- | tiger-compiler/src/overload/binder.cc | 45 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/binder.hh | 65 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/liboverload.cc | 28 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/liboverload.hh | 36 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/local.am | 9 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/over-table.hh | 63 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/over-table.hxx | 64 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/tasks.cc | 38 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/tasks.hh | 29 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/type-checker.cc | 21 | ||||
| -rw-r--r-- | tiger-compiler/src/overload/type-checker.hh | 37 |
11 files changed, 435 insertions, 0 deletions
diff --git a/tiger-compiler/src/overload/binder.cc b/tiger-compiler/src/overload/binder.cc new file mode 100644 index 0000000..14610fe --- /dev/null +++ b/tiger-compiler/src/overload/binder.cc @@ -0,0 +1,45 @@ +/** + ** \file overload/binder.cc + ** \brief Implementation of overload::Binder. + */ + +#include <ast/all.hh> +#include <overload/binder.hh> + +namespace overload +{ + overfun_bindings_type& Binder::overfun_bindings_get() + { + return overfun_bindings_; + } + + /*---------. + | Scopes. | + `---------*/ + + // FIXME: Some code was deleted here. + + /*-------------------. + | Visiting methods. | + `-------------------*/ + + // Same as Binder's, but do not set the definition site of E. + void Binder::operator()(ast::CallExp& e) + { + // FIXME: Some code was deleted here. + } + + // Insert the prototype of the function in the environment. + void Binder::visit_dec_header(ast::FunctionDec& e) + { + // FIXME: Some code was deleted here (Checks for the _main case). + overfuns_.put(e.name_get(), e); + } + + void Binder::operator()(ast::FunctionChunk& e) + { + // Two passes: once on headers, then on bodies. + // FIXME: Some code was deleted here. + } + +} // namespace overload diff --git a/tiger-compiler/src/overload/binder.hh b/tiger-compiler/src/overload/binder.hh new file mode 100644 index 0000000..607debb --- /dev/null +++ b/tiger-compiler/src/overload/binder.hh @@ -0,0 +1,65 @@ +/** + ** \file overload/binder.hh + ** \brief Declaration of overload::Binder. + **/ + +#pragma once + +#include <map> + +#include <bind/binder.hh> +#include <overload/over-table.hh> + +namespace overload +{ + /// Type of the dictionary of potential function bindings. + using overfun_bindings_type = std::multimap<ast::CallExp*, ast::FunctionDec*>; + + /** \brief Computing bindings with support for overloaded functions. + ** + ** This visitor inherits from Binder, but redefines methods + ** dealing with function declarations and uses, to allow + ** overloading. + ** + ** As overloading requires some knowledge of the type of the + ** arguments of a function, no real function binding is done here. + ** We store all potential function declarations (``homonyms'') for + ** each function call, and we'll let the overload::TypeChecker + ** decide later. + ** + ** Inheritance is declared virtual to enable diamond inheritance with + ** the combine::Binder (src/combine/binder.hh), inheriting from + ** overload::Binder and object::Binder, both inheriting from bind::Binder. + **/ + class Binder : virtual public bind::Binder + { + public: + /// Super class type. + using super_type = bind::Binder; + /// Import all the overloaded operator() methods. + using super_type::operator(); + + /* The visiting methods. */ + /// Visit a function call. + void operator()(ast::CallExp& e) override; + + /// Check a function declaration header. + void visit_dec_header(ast::FunctionDec& e); + /// Visit a chunk of function declarations. + void operator()(ast::FunctionChunk& e) override; + + /// Return the function bindings. + overfun_bindings_type& overfun_bindings_get(); + + // FIXME: Some code was deleted here (Overload scope handling). + /** \} */ + + private: + using overtable_type = OverTable<ast::FunctionDec>; + /// The environment of (overloaded) functions. + overtable_type overfuns_; + /// The potential function bindings. + overfun_bindings_type overfun_bindings_; + }; + +} // namespace overload diff --git a/tiger-compiler/src/overload/liboverload.cc b/tiger-compiler/src/overload/liboverload.cc new file mode 100644 index 0000000..7662300 --- /dev/null +++ b/tiger-compiler/src/overload/liboverload.cc @@ -0,0 +1,28 @@ +/** + ** \file overload/liboverload.cc + ** \brief Define exported type functions. + */ + +#include <overload/binder.hh> +#include <overload/liboverload.hh> +#include <overload/type-checker.hh> + +namespace overload +{ + std::pair<overfun_bindings_type, misc::error> bind(ast::Ast& tree) + { + Binder bind; + bind(tree); + return std::pair(std::move(bind.overfun_bindings_get()), + std::move(bind.error_get())); + } + + misc::error types_check(ast::Ast& tree, + const overfun_bindings_type& overfun_bindings) + { + TypeChecker type{overfun_bindings}; + type(tree); + return type.error_get(); + } + +} // namespace overload diff --git a/tiger-compiler/src/overload/liboverload.hh b/tiger-compiler/src/overload/liboverload.hh new file mode 100644 index 0000000..6c89862 --- /dev/null +++ b/tiger-compiler/src/overload/liboverload.hh @@ -0,0 +1,36 @@ +/** + ** \file overload/liboverload.hh + ** \brief Declare functions and variables exported by overload module. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <misc/error.hh> +#include <overload/binder.hh> + +/** + ** \brief Perform type checking, allowing function overloading. + */ +namespace overload +{ + /** \brief Bind identifier uses to their definition, allowing + function overloading, and return a list of potential definition + sites for each function call. + + \param tree AST to bind. + + \return a pair whose first element is the potential function + bindings, and the second element the error status. */ + std::pair<overfun_bindings_type, misc::error> bind(ast::Ast& tree); + + /** \brief Check types allowing function overloading. + + \param tree abstract syntax tree's root. + \param overfun_bindings potential function bindings. + + \return success of the type-checking. */ + misc::error types_check(ast::Ast& tree, + const overfun_bindings_type& overfun_bindings); + +} // namespace overload diff --git a/tiger-compiler/src/overload/local.am b/tiger-compiler/src/overload/local.am new file mode 100644 index 0000000..022ce5f --- /dev/null +++ b/tiger-compiler/src/overload/local.am @@ -0,0 +1,9 @@ +## overload module. + +src_libtc_la_SOURCES += \ + %D%/over-table.hh %D%/over-table.hxx \ + %D%/binder.hh %D%/binder.cc \ + %D%/type-checker.hh %D%/type-checker.cc \ + %D%/liboverload.hh %D%/liboverload.cc + +TASKS += %D%/tasks.hh %D%/tasks.cc diff --git a/tiger-compiler/src/overload/over-table.hh b/tiger-compiler/src/overload/over-table.hh new file mode 100644 index 0000000..04ddb34 --- /dev/null +++ b/tiger-compiler/src/overload/over-table.hh @@ -0,0 +1,63 @@ +/** + ** \file overload/over-table.hh + ** \brief Checking/translating an OverTiger program in a Tiger program. + */ + +#pragma once + +#include <map> +#include <vector> + +namespace overload +{ + template <typename T> class OverTable + { + public: + using map_type = std::multimap<const misc::symbol, T*>; + using iterator = typename map_type::iterator; + using const_iterator = typename map_type::const_iterator; + using oversymtab_type = std::vector<map_type>; + using range_type = std::pair<const_iterator, const_iterator>; + + /// Create a new over table. + OverTable(); + + /// \name Symbol handling + /// \{ + /// Put \a key in the map and add the value to the associated container. + void put(misc::symbol key, T& value); + + /// Return the range associated to the key. + /// + /// If the key is not found, the beginning and the end of the range are + /// equal. + range_type get(misc::symbol key); + /// \} + + /// \name Scopes. + /// \{ + /// \brief Open a new scope. + /// + /// All further type related declarations will be limited to this scope. + void scope_begin(); + + /// \brief Close the last scope. + /// + /// Forget everything (i.e. every type related informations) since the + /// latest scope_begin(). + void scope_end(); + /// \} + + /// Print the table + std::ostream& dump(std::ostream& ostr) const; + + protected: + oversymtab_type oversymtab_; + }; + + template <typename T> + std::ostream& operator<<(std::ostream& ostr, const OverTable<T>& tbl); + +} // namespace overload + +#include <overload/over-table.hxx> diff --git a/tiger-compiler/src/overload/over-table.hxx b/tiger-compiler/src/overload/over-table.hxx new file mode 100644 index 0000000..de8f98b --- /dev/null +++ b/tiger-compiler/src/overload/over-table.hxx @@ -0,0 +1,64 @@ +/** + ** \file overload/over-table.hxx + ** \brief Inline methods and template implementations for overload/over-table.hh. + */ + +#pragma once + +#include <ostream> +#include <ranges> + +#include <overload/over-table.hh> + +namespace overload +{ + template <typename T> OverTable<T>::OverTable() + { + oversymtab_.emplace_back(); + } + + template <typename T> void OverTable<T>::put(misc::symbol key, T& value) + { + oversymtab_.back().emplace(key, &value); + } + + template <typename T> + typename OverTable<T>::range_type OverTable<T>::get(misc::symbol key) + { + precondition(!oversymtab_.empty()); + auto& map = oversymtab_.back(); + return map.equal_range(key); + } + + template <typename T> void OverTable<T>::scope_begin() + { + oversymtab_.emplace_back(oversymtab_.back()); + } + + template <typename T> void OverTable<T>::scope_end() + { + precondition(!oversymtab_.empty()); + oversymtab_.pop_back(); + } + + template <typename T> + std::ostream& OverTable<T>::dump(std::ostream& ostr) const + { + ostr << "<overTable>\n"; + for (const auto& m : oversymtab_ | std::views::reverse) + { + ostr << "<scope>\n"; + for (const auto& im : m) + ostr << im.first << " : " << im->second.size() << '\n'; + ostr << "</scope>\n"; + } + return ostr << "</overTable>\n"; + } + + template <typename T> + std::ostream& operator<<(std::ostream& ostr, const OverTable<T>& tbl) + { + return tbl.dump(ostr); + } + +} // namespace overload diff --git a/tiger-compiler/src/overload/tasks.cc b/tiger-compiler/src/overload/tasks.cc new file mode 100644 index 0000000..9cfde5a --- /dev/null +++ b/tiger-compiler/src/overload/tasks.cc @@ -0,0 +1,38 @@ +/** + ** \file overload/tasks.cc + ** \brief Overload module related tasks' implementation. + */ + +#include <memory> + +#include <ast/tasks.hh> +#include <common.hh> +#include <overload/liboverload.hh> +#define DEFINE_TASKS 1 +#include <overload/tasks.hh> +#undef DEFINE_TASKS + +namespace overload::tasks +{ + std::unique_ptr<overfun_bindings_type> the_overfun_bindings = nullptr; + + void overfun_bindings_compute() + { + auto result = ::overload::bind(*ast::tasks::the_program); + ::overload::tasks::the_overfun_bindings = + std::make_unique<overfun_bindings_type>(std::move(result.first)); + + task_error() << result.second << &misc::error::exit_on_error; + } + + void overfun_types_compute() + { + task_error() << ::overload::types_check( + *ast::tasks::the_program, *::overload::tasks::the_overfun_bindings); + + // Force the unique_ptr to be freed. + the_overfun_bindings.reset(); + task_error().exit_on_error(); + } + +} // namespace overload::tasks diff --git a/tiger-compiler/src/overload/tasks.hh b/tiger-compiler/src/overload/tasks.hh new file mode 100644 index 0000000..31edad1 --- /dev/null +++ b/tiger-compiler/src/overload/tasks.hh @@ -0,0 +1,29 @@ +/** + ** \file overload/tasks.hh + ** \brief Overload module tasks. + */ + +#pragma once + +#include <overload/binder.hh> +#include <task/libtask.hh> + +namespace overload::tasks +{ + TASK_GROUP("4.5 Type checking with overloading"); + + /// Compute bindings, allowing function overloading. + TASK_DECLARE("overfun-bindings-compute", + "bind the identifiers, " + "allowing function overloading", + overfun_bindings_compute, + "parse"); + + /// Check for type violation, allowing function overloading. + TASK_DECLARE("O|overfun-types-compute", + "check for type violations, " + "allowing function overloading", + overfun_types_compute, + "overfun-bindings-compute"); + +} // namespace overload::tasks diff --git a/tiger-compiler/src/overload/type-checker.cc b/tiger-compiler/src/overload/type-checker.cc new file mode 100644 index 0000000..1f32113 --- /dev/null +++ b/tiger-compiler/src/overload/type-checker.cc @@ -0,0 +1,21 @@ +/** + ** \file overload/type-checker.cc + ** \brief Implementation for overload/type-checker.hh. + */ + +#include <algorithm> +#include <sstream> + +#include <misc/indent.hh> +#include <overload/type-checker.hh> +#include <type/types.hh> + +namespace overload +{ + TypeChecker::TypeChecker(const overfun_bindings_type& overfun_bindings) + : overfun_bindings_{overfun_bindings} + {} + + // FIXME: Some code was deleted here. + +} // namespace overload diff --git a/tiger-compiler/src/overload/type-checker.hh b/tiger-compiler/src/overload/type-checker.hh new file mode 100644 index 0000000..719db72 --- /dev/null +++ b/tiger-compiler/src/overload/type-checker.hh @@ -0,0 +1,37 @@ +/** + ** \file overload/type-checker.hh + ** \brief Checking/translating an OverTiger program in a Tiger program. + */ + +#pragma once + +#include <overload/binder.hh> +#include <type/type-checker.hh> +#include <type/types.hh> + +namespace overload +{ + /** \brief Perform type checking, allowing function overload, and compute + ** the bindings of the functions. + ** + ** Inheritance is declared virtual to enable diamond inheritance with + ** the combine::TypeChecker (src/combine/type-checker.hh), inheriting + ** from overload::TypeChecker and object::TypeChecker, both inheriting from + ** type::TypeChecker. + **/ + class TypeChecker : virtual public type::TypeChecker + { + public: + /// Superclass. + using super_type = type::TypeChecker; + using super_type::operator(); + + TypeChecker(const overfun_bindings_type& overfun_bindings); + virtual ~TypeChecker() = default; + + // FIXME: Some code was deleted here. + private: + const overfun_bindings_type& overfun_bindings_; + }; + +} // namespace overload |
