diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2009-09-06 12:52:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2009-09-06 12:52:53 +0200 |
commit | cb9ea47e7825b5073d4d645afb94f6326cb7cf4d (patch) | |
tree | 201c215b08df918924153a60520046c294438a6b /cutl/compiler |
Start the libcutl repository
Diffstat (limited to 'cutl/compiler')
-rw-r--r-- | cutl/compiler/context.cxx | 23 | ||||
-rw-r--r-- | cutl/compiler/context.hxx | 70 | ||||
-rw-r--r-- | cutl/compiler/context.txx | 85 | ||||
-rw-r--r-- | cutl/compiler/traversal.hxx | 155 | ||||
-rw-r--r-- | cutl/compiler/traversal.txx | 145 | ||||
-rw-r--r-- | cutl/compiler/type-id.hxx | 47 | ||||
-rw-r--r-- | cutl/compiler/type-id.ixx | 45 | ||||
-rw-r--r-- | cutl/compiler/type-id.txx | 18 | ||||
-rw-r--r-- | cutl/compiler/type-info.cxx | 31 | ||||
-rw-r--r-- | cutl/compiler/type-info.hxx | 109 | ||||
-rw-r--r-- | cutl/compiler/type-info.ixx | 96 |
11 files changed, 824 insertions, 0 deletions
diff --git a/cutl/compiler/context.cxx b/cutl/compiler/context.cxx new file mode 100644 index 0000000..da31d6e --- /dev/null +++ b/cutl/compiler/context.cxx @@ -0,0 +1,23 @@ +// file : cutl/compiler/context.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include <cutl/compiler/context.hxx> + +namespace cutl +{ + namespace compiler + { + void context:: + remove (char const* key) + { + map::iterator i (map_.find (key)); + + if (i == map_.end ()) + throw no_entry (); + + map_.erase (i); + } + } +} diff --git a/cutl/compiler/context.hxx b/cutl/compiler/context.hxx new file mode 100644 index 0000000..4bae010 --- /dev/null +++ b/cutl/compiler/context.hxx @@ -0,0 +1,70 @@ +// file : cutl/compiler/context.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_COMPILER_CONTEXT_HXX +#define CUTL_COMPILER_CONTEXT_HXX + +#include <map> +#include <string> +#include <cstddef> // std::size_t + +#include <cutl/container/any.hxx> + +namespace cutl +{ + namespace compiler + { + class context + { + public: + struct no_entry {}; + struct typing {}; + + public: + context () {} + + private: + context (context const&); + + context& + operator= (context const&); + + public: + std::size_t + count (char const* key) const + { + return map_.count (key); + } + + template <typename X> + X& + get (char const* key); + + template <typename X> + X const& + get (char const* key) const; + + template <typename X> + X const& + get (char const* key, X const& default_value) const; + + template <typename X> + void + set (char const* key, X const& value); + + void + remove (char const* key); + + private: + typedef std::map<std::string, container::any> map; + + map map_; + }; + } +} + +#include <cutl/compiler/context.txx> + +#endif // CUTL_COMPILER_CONTEXT_HXX diff --git a/cutl/compiler/context.txx b/cutl/compiler/context.txx new file mode 100644 index 0000000..55a24f7 --- /dev/null +++ b/cutl/compiler/context.txx @@ -0,0 +1,85 @@ +// file : cutl/compiler/context.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + template <typename X> + X& context:: + get (char const* key) + { + map::iterator i (map_.find (key)); + + if (i == map_.end ()) + throw no_entry (); + + try + { + return i->second.value<X> (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template <typename X> + X const& context:: + get (char const* key) const + { + map::const_iterator i (map_.find (key)); + + if (i == map_.end ()) + throw no_entry (); + + try + { + return i->second.value<X> (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template <typename X> + X const& context:: + get (char const* key, X const& default_value) const + { + map::const_iterator i (map_.find (key)); + + if (i == map_.end ()) + return default_value; + + try + { + return i->second.value<X> (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template <typename X> + void context:: + set (char const* key, X const& value) + { + try + { + std::pair<map::iterator, bool> r ( + map_.insert (map::value_type (key, value))); + + if (!r.second) + r.first->second.value<X> () = value; + } + catch (container::any::typing const&) + { + throw typing (); + } + } + } +} diff --git a/cutl/compiler/traversal.hxx b/cutl/compiler/traversal.hxx new file mode 100644 index 0000000..ad677b0 --- /dev/null +++ b/cutl/compiler/traversal.hxx @@ -0,0 +1,155 @@ +// file : cutl/compiler/traversal.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_COMPILER_TRAVERSAL_HXX +#define CUTL_COMPILER_TRAVERSAL_HXX + +#include <map> +#include <set> +#include <vector> + +#include <cutl/compiler/type-info.hxx> + +namespace cutl +{ + namespace compiler + { + // + // + template<typename B> + class traverser + { + public: + virtual + ~traverser (); + + virtual void + trampoline (B&) = 0; + }; + + // + // + template<typename B> + class traverser_map + { + public: + typedef std::vector<traverser<B>*> traversers; + typedef std::map<type_id, traversers> map_type; + typedef typename map_type::const_iterator iterator; + + iterator + begin () const + { + return map_.begin (); + } + + iterator + end () const + { + return map_.end (); + } + + void + add (type_id const& id, traverser<B>& t) + { + traversers& travs (map_[id]); + travs.push_back (&t); + } + + protected: + map_type map_; + }; + + // + // + template <typename X, typename B> + class traverser_impl: public traverser<B>, + public virtual traverser_map<B> + { + public: + typedef X type; + + traverser_impl () + { + add (typeid (type), *this); + } + + virtual void + traverse (type&) = 0; + + public: + virtual void + trampoline (B&); + }; + + // + // + template <typename B> + class dispatcher: public virtual traverser_map<B> + { + public: + virtual + ~dispatcher (); + + void + traverser (traverser_map<B>&); + + virtual void + dispatch (B&); + + public: + template <typename I, typename X> + static void + iterate_and_dispatch (I begin, I end, dispatcher<X>& d) + { + for (; begin != end; ++begin) + { + d.dispatch (*begin); + } + } + + template <typename T, typename A, typename I, typename X> + static void + iterate_and_dispatch (I begin, + I end, + dispatcher<X>& d, + T& t, + void (T::*next)(A&), + A& a) + { + for (; begin != end;) + { + d.dispatch (*begin); + + if (++begin != end && next != 0) + (t.*next) (a); + } + } + + private: + struct comparator + { + bool + operator () (type_info const& a, type_info const& b) const + { + return a.type_id () < b.type_id (); + } + }; + + typedef std::map<type_info, std::size_t, comparator> level_map; + typedef std::set<type_info, comparator> type_info_set; + + static std::size_t + compute_levels (type_info const&, std::size_t current, level_map&); + + static void + flatten_tree (type_info const&, type_info_set&); + }; + } +} + +#include <cutl/compiler/traversal.txx> + +#endif // CUTL_COMPILER_TRAVERSAL_HXX diff --git a/cutl/compiler/traversal.txx b/cutl/compiler/traversal.txx new file mode 100644 index 0000000..315d11b --- /dev/null +++ b/cutl/compiler/traversal.txx @@ -0,0 +1,145 @@ +// file : cutl/compiler/traversal.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + // traverser + // + template<typename B> + traverser<B>:: + ~traverser () + { + } + + // traverser_impl + // + + template <typename X, typename B> + void traverser_impl<X, B>:: + trampoline (B& x) + { + this->traverse (dynamic_cast<type&> (x)); + } + + // dispatcher + // + + template <typename B> + dispatcher<B>:: + ~dispatcher () + { + } + + template <typename B> + void dispatcher<B>:: + traverser (traverser_map<B>& m) + { + // Copy entries from m to our map. + // + for (typename traverser_map<B>::iterator + i (m.begin ()), e (m.end ()); i != e; ++i) + { + typename traverser_map<B>::traversers& travs (this->map_[i->first]); + + for (typename traverser_map<B>::traversers::const_iterator + t (i->second.begin ()), e (i->second.end ()); t != e; ++t) + { + travs.push_back (*t); + } + } + } + + template <typename B> + void dispatcher<B>:: + dispatch (B& x) + { + using std::size_t; + + level_map levels; + type_info const& ti (lookup (x)); + size_t max (compute_levels (ti, 0, levels)); + + // cerr << "starting dispatch process for " << ti.type_id ().name () + // << " with " << max << " levels" << endl; + + for (size_t l (0); l < max + 1; ++l) + { + type_info_set dispatched; + + for (typename level_map::const_iterator + i (levels.begin ()), e (levels.end ()); i != e; ++i) + { + if (i->second == l) + { + typename traverser_map<B>::map_type::const_iterator v ( + this->map_.find (i->first.type_id ())); + + if (v != this->map_.end ()) + { + // cerr << "dispatching traversers for " << ti.type_id ().name () + // << " as " << i->first.type_id ().name () << endl; + + typename traverser_map<B>::traversers const& travs (v->second); + + for (typename traverser_map<B>::traversers::const_iterator + ti (travs.begin ()), te (travs.end ()); ti != te; ++ti) + { + (*ti)->trampoline (x); + } + + flatten_tree (i->first, dispatched); + } + } + } + + // Remove traversed types from the level map. + // + for (typename type_info_set::const_iterator i (dispatched.begin ()); + i != dispatched.end (); ++i) + { + levels.erase (*i); + } + } + } + + template <typename B> + std::size_t dispatcher<B>:: + compute_levels (type_info const& ti, std::size_t cur, level_map& map) + { + using std::size_t; + + size_t ret (cur); + + if (map.find (ti) == map.end () || map[ti] < cur) + map[ti] = cur; + + for (type_info::base_iterator i (ti.begin_base ()); + i != ti.end_base (); ++i) + { + size_t tmp (compute_levels (i->type_info (), cur + 1, map)); + + if (tmp > ret) + ret = tmp; + } + + return ret; + } + + template <typename B> + void dispatcher<B>:: + flatten_tree (type_info const& ti, type_info_set& set) + { + set.insert (ti); + + for (type_info::base_iterator i (ti.begin_base ()); + i != ti.end_base (); ++i) + { + flatten_tree (i->type_info (), set); + } + } + } +} diff --git a/cutl/compiler/type-id.hxx b/cutl/compiler/type-id.hxx new file mode 100644 index 0000000..7731f6d --- /dev/null +++ b/cutl/compiler/type-id.hxx @@ -0,0 +1,47 @@ +// file : cutl/compiler/type-id.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_COMPILER_TYPE_ID_HXX +#define CUTL_COMPILER_TYPE_ID_HXX + +#include <typeinfo> // std::type_info + +namespace cutl +{ + namespace compiler + { + class type_id + { + public: + template<typename X> + type_id (X const volatile&); + + type_id (std::type_info const&); + + public: + char const* + name () const; + + friend bool + operator== (type_id const&, type_id const&); + + friend bool + operator!= (type_id const&, type_id const&); + + friend bool + operator< (type_id const&, type_id const&); + + private: + std::type_info const* ti_; + }; + + typedef type_id type_id_t; + } +} + +#include <cutl/compiler/type-id.ixx> +#include <cutl/compiler/type-id.txx> + +#endif // CUTL_COMPILER_TYPE_ID_HXX diff --git a/cutl/compiler/type-id.ixx b/cutl/compiler/type-id.ixx new file mode 100644 index 0000000..4092d6d --- /dev/null +++ b/cutl/compiler/type-id.ixx @@ -0,0 +1,45 @@ +// file : cutl/compiler/type-id.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + inline + type_id:: + type_id (std::type_info const& ti) + : ti_ (&ti) + { + } + + inline + char const* type_id:: + name () const + { + return ti_->name (); + } + + inline + bool + operator== (type_id const& x, type_id const& y) + { + return *x.ti_ == *y.ti_; + } + + inline + bool + operator!= (type_id const& x, type_id const& y) + { + return *x.ti_ != *y.ti_; + } + + inline + bool + operator< (type_id const& x, type_id const& y) + { + return x.ti_->before (*y.ti_); + } + } +} diff --git a/cutl/compiler/type-id.txx b/cutl/compiler/type-id.txx new file mode 100644 index 0000000..9fee905 --- /dev/null +++ b/cutl/compiler/type-id.txx @@ -0,0 +1,18 @@ +// file : cutl/compiler/type-id.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + template <typename X> + inline + type_id:: + type_id (X const volatile& x) + : ti_ (&typeid (x)) + { + } + } +} diff --git a/cutl/compiler/type-info.cxx b/cutl/compiler/type-info.cxx new file mode 100644 index 0000000..4be7177 --- /dev/null +++ b/cutl/compiler/type-info.cxx @@ -0,0 +1,31 @@ +// file : cutl/compiler/type-info.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +namespace cutl +{ + namespace compiler + { + using namespace bits; + + type_info const& + lookup (type_id const& tid) + { + type_info_map::const_iterator i (type_info_map_->find (tid)); + + if (i == type_info_map_->end ()) + throw no_type_info (); + + return i->second; + } + + void + insert (type_info const& ti) + { + type_info_map_->insert (type_info_map::value_type (ti.type_id (), ti)); + } + } +} diff --git a/cutl/compiler/type-info.hxx b/cutl/compiler/type-info.hxx new file mode 100644 index 0000000..f970067 --- /dev/null +++ b/cutl/compiler/type-info.hxx @@ -0,0 +1,109 @@ +// file : cutl/compiler/type-info.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_COMPILER_TYPE_INFO_HXX +#define CUTL_COMPILER_TYPE_INFO_HXX + +#include <map> +#include <vector> +#include <typeinfo> // std::type_info + +#include <cutl/static-ptr.hxx> +#include <cutl/compiler/type-id.hxx> + +namespace cutl +{ + namespace compiler + { + // + // + class type_info; + typedef type_info type_info_t; + + + // + // + class base_info + { + public: + base_info (type_id const&); + + public: + type_info_t const& + type_info () const; + + private: + type_id type_id_; + mutable type_info_t const* type_info_; + }; + + typedef base_info base_info_t; + + + // + // + class type_info + { + typedef std::vector<base_info> bases; + + public: + typedef + bases::const_iterator + base_iterator; + + public: + type_info (type_id_t const&); + + type_id_t + type_id () const; + + base_iterator + begin_base () const; + + base_iterator + end_base () const; + + void + add_base (type_id_t const&); + + private: + type_id_t type_id_; + bases bases_; + }; + + + // + // + class no_type_info {}; + + type_info const& + lookup (type_id const&); + + type_info const& + lookup (std::type_info const&); + + template <typename X> + type_info const& + lookup (X const volatile&); + + template<typename X> + type_info const& + lookup (); + + void + insert (type_info const&); + + namespace bits + { + struct default_type_info_id {}; + typedef std::map<type_id, type_info> type_info_map; + static static_ptr<type_info_map, default_type_info_id> type_info_map_; + } + } +} + +#include <cutl/compiler/type-info.ixx> + +#endif // CUTL_COMPILER_TYPE_INFO_HXX diff --git a/cutl/compiler/type-info.ixx b/cutl/compiler/type-info.ixx new file mode 100644 index 0000000..3f1bb86 --- /dev/null +++ b/cutl/compiler/type-info.ixx @@ -0,0 +1,96 @@ +// file : cutl/compiler/type-info.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + // base_info + // + + inline + base_info:: + base_info (type_id const& type_id) + : type_id_ (type_id), type_info_ (0) + { + } + + inline + type_info_t const& base_info:: + type_info () const + { + // We need to do delayed lookup because of the unpredictable + // order in which type information may be added. + // + // @@ MT-unsafe + // + if (type_info_ == 0) + type_info_ = &(lookup (type_id_)); + + return *type_info_; + } + + // type_info + // + + inline + type_info:: + type_info (type_id_t const& tid) + : type_id_ (tid) + { + } + + inline + type_id_t type_info:: + type_id () const + { + return type_id_; + } + + inline + type_info::base_iterator type_info:: + begin_base () const + { + return bases_.begin (); + } + + + inline + type_info::base_iterator type_info:: + end_base () const + { + return bases_.end (); + } + + inline + void type_info:: + add_base (type_id_t const& tid) + { + bases_.push_back (base_info (tid)); + } + + // + // + inline type_info const& + lookup (std::type_info const& tid) + { + return lookup (type_id (tid)); + } + + template <typename X> + inline type_info const& + lookup (X const volatile& x) + { + return lookup (typeid (x)); + } + + template<typename X> + inline type_info const& + lookup () + { + return lookup (typeid (X)); + } + } +} |