aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-09-06 12:52:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-09-06 12:52:53 +0200
commitcb9ea47e7825b5073d4d645afb94f6326cb7cf4d (patch)
tree201c215b08df918924153a60520046c294438a6b
Start the libcutl repository
-rw-r--r--INSTALL28
-rw-r--r--LICENSE21
-rw-r--r--NEWS3
-rw-r--r--README12
-rw-r--r--TODO2
-rw-r--r--build/bootstrap.make51
-rw-r--r--build/export/libcutl/stub.make10
l---------build/import/libcutl/LICENSE1
-rw-r--r--build/import/libcutl/configuration-rules.make15
-rwxr-xr-xbuild/import/libcutl/configure55
-rw-r--r--build/import/libcutl/stub.make30
-rw-r--r--cutl/compiler/context.cxx23
-rw-r--r--cutl/compiler/context.hxx70
-rw-r--r--cutl/compiler/context.txx85
-rw-r--r--cutl/compiler/traversal.hxx155
-rw-r--r--cutl/compiler/traversal.txx145
-rw-r--r--cutl/compiler/type-id.hxx47
-rw-r--r--cutl/compiler/type-id.ixx45
-rw-r--r--cutl/compiler/type-id.txx18
-rw-r--r--cutl/compiler/type-info.cxx31
-rw-r--r--cutl/compiler/type-info.hxx109
-rw-r--r--cutl/compiler/type-info.ixx96
-rw-r--r--cutl/container/any.hxx133
-rw-r--r--cutl/container/graph.hxx157
-rw-r--r--cutl/container/graph.txx315
-rw-r--r--cutl/container/pointer-iterator.hxx127
-rw-r--r--cutl/makefile47
-rw-r--r--cutl/meta/answer.hxx25
-rw-r--r--cutl/meta/class-p.hxx27
-rw-r--r--cutl/meta/polymorphic-p.hxx51
-rw-r--r--cutl/meta/remove-c.hxx27
-rw-r--r--cutl/meta/remove-cv.hxx24
-rw-r--r--cutl/meta/remove-p.hxx27
-rw-r--r--cutl/meta/remove-v.hxx27
-rw-r--r--cutl/shared-ptr.hxx135
-rw-r--r--cutl/shared-ptr/base.cxx63
-rw-r--r--cutl/shared-ptr/base.hxx90
-rw-r--r--cutl/shared-ptr/base.ixx79
-rw-r--r--cutl/shared-ptr/base.txx174
-rw-r--r--cutl/static-ptr.hxx75
-rw-r--r--doc/components.txt6
-rw-r--r--makefile42
-rw-r--r--tests/compiler/makefile18
-rw-r--r--tests/compiler/traversal/driver.cxx135
-rw-r--r--tests/compiler/traversal/makefile71
-rw-r--r--tests/compiler/traversal/output.std16
-rw-r--r--tests/makefile18
-rw-r--r--tests/shared-ptr/driver.cxx186
-rw-r--r--tests/shared-ptr/makefile70
-rw-r--r--version1
50 files changed, 3218 insertions, 0 deletions
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..d7ed7e2
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,28 @@
+UNIX
+----
+
+Building on UNIX-like operating systems requires GNU make 3.81 or later.
+Most recent GNU/Linux distributions should already have this version
+installed. To check the GNU make version run make (or gmake) with the
+--version option.
+
+Unless you are using the libcutl+dep package, you will also need to
+install the following dependencies:
+
+ build >= 0.3.4 http://kolpackov.net/projects/build/
+
+The libcutl+dep package comes with the necessary dependencies bundled.
+
+To build the library, tests, and examples simply run make in the root
+directory of the package. To run the automated tests, run 'make test'.
+To clean the object file, executables, etc., run 'make clean'. To de-
+configure the package (that is, remove configuration files in addition
+to objects, executables, etc.), run 'make disfigure'.
+
+
+Windows
+-------
+
+Project and solution files for Visual C++ will be provided in the future.
+For now, you can create an empty library project and add all the source
+files in the cutl/ directory to it.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5306eea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) Code Synthesis Tools CC, 2009.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..a4e1bbf
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,3 @@
+Version 1.0.0
+
+ * First public release.
diff --git a/README b/README
new file mode 100644
index 0000000..d18c36e
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+libcutl is a C++ utility library. It contains a collection of generic and
+fairly independent components. See doc/components.txt for an overview.
+
+See the NEWS file for the user-visible changes from the previous release.
+
+See the LICENSE file for distribution conditions.
+
+See the INSTALL file for prerequisites and installation instructions.
+
+See the doc/ directory for documentation.
+
+Send questions, bug reports, or any other feedback to boris@codesynthesis.com
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..25de54b
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+@@ Common exception class (print typeid(*this).name () in what()).
+@@ Add memprof?
diff --git a/build/bootstrap.make b/build/bootstrap.make
new file mode 100644
index 0000000..7720553
--- /dev/null
+++ b/build/bootstrap.make
@@ -0,0 +1,51 @@
+# file : build/bootstrap.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+project_name := libcutl
+
+# First try to include the bundled bootstrap.make if it exist. If that
+# fails, let make search for the external bootstrap.make.
+#
+build := build-0.3
+
+-include $(dir $(lastword $(MAKEFILE_LIST)))../../$(build)/bootstrap.make
+
+ifeq ($(patsubst %build/bootstrap.make,,$(lastword $(MAKEFILE_LIST))),)
+include $(build)/bootstrap.make
+endif
+
+
+# Aliases
+#
+.PHONY: $(out_base)/ \
+ $(out_base)/.test \
+ $(out_base)/.install \
+ $(out_base)/.dist \
+ $(out_base)/.clean
+
+ifdef %interactive%
+
+.PHONY: test install dist clean
+
+test: $(out_base)/.test
+install: $(out_base)/.install
+dist: $(out_base)/.dist
+clean: $(out_base)/.clean
+
+ifneq ($(filter $(.DEFAULT_GOAL),test install dist clean),)
+.DEFAULT_GOAL :=
+endif
+
+endif
+
+# Don't include dependency info for certain targets.
+#
+define include-dep
+$(call -include,$1)
+endef
+
+ifneq ($(filter $(MAKECMDGOALS),clean disfigure),)
+include-dep =
+endif
diff --git a/build/export/libcutl/stub.make b/build/export/libcutl/stub.make
new file mode 100644
index 0000000..165d5e0
--- /dev/null
+++ b/build/export/libcutl/stub.make
@@ -0,0 +1,10 @@
+# file : build/export/libcutl/stub.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+$(call include-once,$(src_root)/cutl/makefile,$(out_root))
+
+$(call export,\
+ l: $(out_root)/cutl/cutl.l,\
+ cpp-options: $(out_root)/cutl/cutl.l.cpp-options)
diff --git a/build/import/libcutl/LICENSE b/build/import/libcutl/LICENSE
new file mode 120000
index 0000000..5853aae
--- /dev/null
+++ b/build/import/libcutl/LICENSE
@@ -0,0 +1 @@
+../../../LICENSE \ No newline at end of file
diff --git a/build/import/libcutl/configuration-rules.make b/build/import/libcutl/configuration-rules.make
new file mode 100644
index 0000000..e2fefb7
--- /dev/null
+++ b/build/import/libcutl/configuration-rules.make
@@ -0,0 +1,15 @@
+# file : build/import/libcutl/configuration-rules.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+$(dcf_root)/import/libcutl/configuration-dynamic.make: | $(dcf_root)/import/libcutl/.
+ $(call message,,$(scf_root)/import/libcutl/configure $@)
+
+ifndef %foreign%
+
+disfigure::
+ $(call message,rm $(dcf_root)/import/libcutl/configuration-dynamic.make,\
+rm -f $(dcf_root)/import/libcutl/configuration-dynamic.make)
+
+endif
diff --git a/build/import/libcutl/configure b/build/import/libcutl/configure
new file mode 100755
index 0000000..b06e6f5
--- /dev/null
+++ b/build/import/libcutl/configure
@@ -0,0 +1,55 @@
+#! /usr/bin/env bash
+
+# file : build/import/libcutl/configure
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+
+# $1 - out file
+#
+# bld_root - build root
+# project_name - project name
+#
+
+source $bld_root/dialog.bash
+
+
+$echo
+$echo "Configuring external dependency on 'libcutl' for '$project_name'."
+$echo
+
+$echo
+$echo "Would you like to configure dependency on the installed "
+$echo "version of 'libcutl' as opposed to the development build?"
+$echo
+
+installed=`read_y_n y`
+
+path=
+
+if [ "$installed" = "n" ]; then
+
+$echo
+$echo "Please enter the src_root for 'libcutl'."
+$echo
+
+src_root=`read_path --directory --exist`
+
+$echo
+$echo "Please enter the out_root for 'libcutl'."
+$echo
+
+out_root=`read_path --directory $src_root`
+
+fi
+
+echo libcutl_installed := $installed >$1
+
+if [ "$installed" = "n" ]; then
+
+echo src_root := $src_root >>$1
+echo scf_root := \$\(src_root\)/build >>$1
+echo out_root := $out_root >>$1
+
+fi
diff --git a/build/import/libcutl/stub.make b/build/import/libcutl/stub.make
new file mode 100644
index 0000000..15fa9dd
--- /dev/null
+++ b/build/import/libcutl/stub.make
@@ -0,0 +1,30 @@
+# file : build/import/libcutl/stub.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+$(call include-once,$(scf_root)/import/libcutl/configuration-rules.make,$(dcf_root))
+
+libcutl_installed :=
+
+$(call -include,$(dcf_root)/import/libcutl/configuration-dynamic.make)
+
+ifdef libcutl_installed
+
+ifeq ($(libcutl_installed),y)
+
+$(call export,l: -lcutl,cpp-options: )
+
+else
+
+# Include export stub.
+#
+$(call include,$(scf_root)/export/libcutl/stub.make)
+
+endif
+
+else
+
+.NOTPARALLEL:
+
+endif
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));
+ }
+ }
+}
diff --git a/cutl/container/any.hxx b/cutl/container/any.hxx
new file mode 100644
index 0000000..0c89a38
--- /dev/null
+++ b/cutl/container/any.hxx
@@ -0,0 +1,133 @@
+// file : cutl/container/any.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_ANY_HXX
+#define CUTL_CONTAINER_ANY_HXX
+
+#include <memory> // std::auto_ptr
+#include <typeinfo> // std::type_info
+
+namespace cutl
+{
+ namespace container
+ {
+ class any
+ {
+ public:
+ struct typing {};
+
+ public:
+ template <typename X>
+ any (X const& x)
+ : holder_ (new holder_impl<X> (x))
+ {
+ }
+
+ any (any const& x)
+ : holder_ (x.holder_->clone ())
+ {
+ }
+
+ template <typename X>
+ any&
+ operator= (X const& x)
+ {
+ holder_.reset (new holder_impl<X> (x));
+ return *this;
+ }
+
+ any&
+ operator= (any const& x)
+ {
+ holder_.reset (x.holder_->clone ());
+ return *this;
+ }
+
+ public:
+ template <typename X>
+ X&
+ value ()
+ {
+ if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
+ return p->value ();
+ else
+ throw typing ();
+ }
+
+ template <typename X>
+ X const&
+ value () const
+ {
+ if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
+ return p->value ();
+ else
+ throw typing ();
+ }
+
+ public:
+ std::type_info const&
+ type_info () const
+ {
+ return holder_->type_info ();
+ }
+
+ private:
+ class holder
+ {
+ public:
+ virtual
+ ~holder () {}
+
+ virtual holder*
+ clone () const = 0;
+
+ virtual std::type_info&
+ type_info () const = 0;
+ };
+
+ template <typename X>
+ class holder_impl: public holder
+ {
+ public:
+ holder_impl (X const& x)
+ : x_ (x)
+ {
+ }
+
+ virtual holder_impl*
+ clone () const
+ {
+ return new holder_impl (x_);
+ }
+
+ virtual std::type_info&
+ type_info () const
+ {
+ return typeid (x_);
+ }
+
+ X const&
+ value () const
+ {
+ return x_;
+ }
+
+ X&
+ value ()
+ {
+ return x_;
+ }
+
+ private:
+ X x_;
+ };
+
+ private:
+ std::auto_ptr<holder> holder_;
+ };
+ }
+}
+
+#endif // CUTL_CONTAINER_ANY_HXX
diff --git a/cutl/container/graph.hxx b/cutl/container/graph.hxx
new file mode 100644
index 0000000..9d1c716
--- /dev/null
+++ b/cutl/container/graph.hxx
@@ -0,0 +1,157 @@
+// file : cutl/container/graph.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_GRAPH_HXX
+#define CUTL_CONTAINER_GRAPH_HXX
+
+#include <map>
+#include <cutl/shared-ptr.hxx>
+
+namespace cutl
+{
+ namespace container
+ {
+ template <typename N, typename E>
+ class graph
+ {
+ public:
+ typedef N node_base;
+ typedef E edge_base;
+
+ struct no_edge {};
+
+ public:
+ template <typename T>
+ T&
+ new_node ();
+
+ template <typename T, typename A0>
+ T&
+ new_node (A0 const&);
+
+ template <typename T, typename A0, typename A1>
+ T&
+ new_node (A0 const&, A1 const&);
+
+ template <typename T, typename A0, typename A1, typename A2>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&, A9 const&);
+
+ // template <typename T>
+ // void
+ // delete_node (T& node);
+
+ public:
+ template <typename T, typename L, typename R>
+ T&
+ new_edge (L&, R&);
+
+ template <typename T, typename L, typename R,
+ typename A0>
+ T&
+ new_edge (L&, R&, A0 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&, A5 const&);
+
+ public:
+ template <typename T, typename L, typename R>
+ void
+ delete_edge (L&, R&, T& edge);
+
+ public:
+ graph () {}
+
+ private:
+ graph (graph const&);
+
+ graph&
+ operator= (graph const&);
+
+ protected:
+ typedef shared_ptr<node_base> node_ptr;
+ typedef shared_ptr<edge_base> edge_ptr;
+
+ typedef std::map<node_base*, node_ptr> nodes;
+ typedef std::map<edge_base*, edge_ptr> edges;
+
+ nodes nodes_;
+ edges edges_;
+ };
+ }
+}
+
+#include <cutl/container/graph.txx>
+
+#endif // CUTL_CONTAINER_GRAPH_HXX
diff --git a/cutl/container/graph.txx b/cutl/container/graph.txx
new file mode 100644
index 0000000..534b0ac
--- /dev/null
+++ b/cutl/container/graph.txx
@@ -0,0 +1,315 @@
+// file : cutl/container/graph.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace container
+ {
+
+ // Nodes.
+ //
+
+ template <typename N, typename E>
+ template <typename T>
+ T& graph<N, E>::
+ new_node ()
+ {
+ shared_ptr<T> node (new (shared) T);
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0>
+ T& graph<N, E>::
+ new_node (A0 const& a0)
+ {
+ shared_ptr<T> node (new (shared) T (a0));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5, a6));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8)
+ {
+ shared_ptr<T> node (
+ new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8, A9 const& a9)
+ {
+ shared_ptr<T> node (
+ new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ // Edges.
+ //
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R>
+ T& graph<N, E>::
+ new_edge (L& l, R& r)
+ {
+ shared_ptr<T> edge (new (shared) T);
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0)
+ {
+ shared_ptr<T> edge (new (shared) T (a0));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3, a4));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4, A5 const& a5)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3, a4, a5));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R>
+ void graph<N, E>::
+ delete_edge (L& l, R& r, T& edge)
+ {
+ typename edges::iterator i (edges_.find (&edge));
+
+ if (i == edges_.end () ||
+ nodes_.find (&l) == nodes_.end () ||
+ nodes_.find (&r) == nodes_.end ())
+ throw no_edge ();
+
+ r.remove_edge_right (edge);
+ l.remove_edge_left (edge);
+
+ edge.clear_right_node (r);
+ edge.clear_left_node (l);
+
+ edges_.erase (i);
+ }
+ }
+}
diff --git a/cutl/container/pointer-iterator.hxx b/cutl/container/pointer-iterator.hxx
new file mode 100644
index 0000000..cc94151
--- /dev/null
+++ b/cutl/container/pointer-iterator.hxx
@@ -0,0 +1,127 @@
+// file : cutl/container/pointer-iterator.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_POINTER_ITERATOR_HXX
+#define CUTL_CONTAINER_POINTER_ITERATOR_HXX
+
+#include <iterator> // std::iterator_traits
+
+#include <cutl/meta/remove-p.hxx>
+
+namespace cutl
+{
+ namespace container
+ {
+ template <typename I>
+ class pointer_iterator
+ {
+ public:
+ typedef
+ typename meta::remove_p<typename std::iterator_traits<I>::value_type>::r
+ value_type;
+
+ typedef
+ typename std::iterator_traits<I>::iterator_category
+ iterator_category;
+
+ typedef
+ typename std::iterator_traits<I>::difference_type
+ difference_type;
+
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef I base_iterator;
+
+ public:
+ pointer_iterator ()
+ : i_ () // I can be of a pointer type.
+ {
+ }
+
+ pointer_iterator (I const& i)
+ : i_ (i)
+ {
+ }
+
+ public:
+ reference
+ operator* () const
+ {
+ return **i_;
+ }
+
+ pointer
+ operator-> () const
+ {
+ return *i_;
+ }
+
+ I const&
+ base () const
+ {
+ return i_;
+ }
+
+ public:
+ // Forward iterator requirements.
+ //
+ pointer_iterator&
+ operator++ ()
+ {
+ ++i_;
+ return *this;
+ }
+
+ pointer_iterator
+ operator++ (int)
+ {
+ pointer_iterator r (*this);
+ ++i_;
+ return r;
+ }
+
+ pointer_iterator&
+ operator-- ()
+ {
+ --i_;
+ return *this;
+ }
+
+ pointer_iterator
+ operator-- (int)
+ {
+ pointer_iterator r (*this);
+ --i_;
+ return r;
+ }
+
+ private:
+ I i_;
+ };
+
+ template <typename I>
+ inline bool
+ operator== (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () == b.base ();
+ }
+
+ template <typename I>
+ inline bool
+ operator!= (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () != b.base ();
+ }
+
+ template <typename I>
+ inline typename pointer_iterator<I>::difference_type
+ operator- (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () - b.base ();
+ }
+ }
+}
+
+#endif // CUTL_CONTAINER_POINTER_ITERATOR_HXX
diff --git a/cutl/makefile b/cutl/makefile
new file mode 100644
index 0000000..b27f090
--- /dev/null
+++ b/cutl/makefile
@@ -0,0 +1,47 @@
+# file : cutl/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+cxx_tun := shared-ptr/base.cxx
+cxx_tun += compiler/context.cxx compiler/type-info.cxx
+
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cutl.l := $(out_base)/cutl.l
+cutl.l.cpp-options := $(out_base)/cutl.l.cpp-options
+
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(cutl.l): $(cxx_obj)
+
+$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options)
+$(cutl.l.cpp-options): value := -I$(src_root)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(cutl.l)
+
+
+# Clean.
+#
+$(clean): $(cutl.l).o.clean \
+ $(cutl.l.cpp-options).clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-l.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
diff --git a/cutl/meta/answer.hxx b/cutl/meta/answer.hxx
new file mode 100644
index 0000000..f476dd7
--- /dev/null
+++ b/cutl/meta/answer.hxx
@@ -0,0 +1,25 @@
+// file : cutl/meta/answer.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_ANSWER_HXX
+#define CUTL_META_ANSWER_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ struct yes
+ {
+ char filling;
+ };
+
+ struct no
+ {
+ char filling[2];
+ };
+ }
+}
+
+#endif // CUTL_META_ANSWER_HXX
diff --git a/cutl/meta/class-p.hxx b/cutl/meta/class-p.hxx
new file mode 100644
index 0000000..79e8469
--- /dev/null
+++ b/cutl/meta/class-p.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/class-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_CLASS_HXX
+#define CUTL_META_CLASS_HXX
+
+#include <cutl/meta/answer.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct class_p
+ {
+ template <typename Y> static no test (...);
+ template <typename Y> static yes test (void* Y::*);
+
+ static bool const r = sizeof (
+ class_p<X>::template test<X> (0)) == sizeof (yes);
+ };
+ }
+}
+
+#endif // CUTL_META_CLASS_HXX
diff --git a/cutl/meta/polymorphic-p.hxx b/cutl/meta/polymorphic-p.hxx
new file mode 100644
index 0000000..35723e3
--- /dev/null
+++ b/cutl/meta/polymorphic-p.hxx
@@ -0,0 +1,51 @@
+// file : cutl/meta/polymorphic-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_POLYMORPHIC_HXX
+#define CUTL_META_POLYMORPHIC_HXX
+
+#include <cutl/meta/class-p.hxx>
+#include <cutl/meta/remove-cv.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename CVX>
+ struct polymorphic_p
+ {
+ typedef typename remove_cv<CVX>::r X;
+
+ template <typename Y, bool C>
+ struct impl
+ {
+ static const bool r = false;
+ };
+
+ template <typename Y>
+ struct impl<Y, true>
+ {
+ struct t1: Y
+ {
+ t1 ();
+ };
+
+ struct t2: Y
+ {
+ t2 ();
+
+ virtual
+ ~t2 () throw ();
+ };
+
+ static const bool r = sizeof (t1) == sizeof (t2);
+ };
+
+ static const bool r = impl<X, class_p<X>::r>::r;
+ };
+ }
+}
+
+#endif // CUTL_META_POLYMORPHIC_HXX
diff --git a/cutl/meta/remove-c.hxx b/cutl/meta/remove-c.hxx
new file mode 100644
index 0000000..be7b8a6
--- /dev/null
+++ b/cutl/meta/remove-c.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-c.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_C_HXX
+#define CUTL_META_REMOVE_C_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_c
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_c<X const>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_C_HXX
diff --git a/cutl/meta/remove-cv.hxx b/cutl/meta/remove-cv.hxx
new file mode 100644
index 0000000..5a7de7a
--- /dev/null
+++ b/cutl/meta/remove-cv.hxx
@@ -0,0 +1,24 @@
+// file : cutl/meta/remove-cv.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_CV_HXX
+#define CUTL_META_REMOVE_CV_HXX
+
+#include <cutl/meta/remove-c.hxx>
+#include <cutl/meta/remove-v.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_cv
+ {
+ typedef typename remove_v<typename remove_c<X>::r>::r r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_CV_HXX
diff --git a/cutl/meta/remove-p.hxx b/cutl/meta/remove-p.hxx
new file mode 100644
index 0000000..56c4517
--- /dev/null
+++ b/cutl/meta/remove-p.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_P_HXX
+#define CUTL_META_REMOVE_P_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_p
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_p<X*>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_P_HXX
diff --git a/cutl/meta/remove-v.hxx b/cutl/meta/remove-v.hxx
new file mode 100644
index 0000000..9f2ae46
--- /dev/null
+++ b/cutl/meta/remove-v.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-v.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_V_HXX
+#define CUTL_META_REMOVE_V_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_v
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_v<X volatile>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_V_HXX
diff --git a/cutl/shared-ptr.hxx b/cutl/shared-ptr.hxx
new file mode 100644
index 0000000..d94bf97
--- /dev/null
+++ b/cutl/shared-ptr.hxx
@@ -0,0 +1,135 @@
+// file : cutl/shared-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_SHARED_PTR_HXX
+#define CUTL_SHARED_PTR_HXX
+
+#include <cutl/shared-ptr/base.hxx>
+
+namespace cutl
+{
+ template <typename X>
+ class shared_ptr: bits::counter_ops<typename bits::counter_type<X>::r, X>
+ {
+ typedef bits::counter_ops<typename bits::counter_type<X>::r, X> base;
+
+ public:
+ ~shared_ptr ()
+ {
+ if (x_ != 0)
+ base::dec (x_);
+ }
+
+ explicit
+ shared_ptr (X* x = 0)
+ : base (x), x_ (x)
+ {
+ }
+
+ shared_ptr (shared_ptr const& x)
+ : base (x), x_ (x.x_)
+ {
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ template <typename Y>
+ shared_ptr (shared_ptr<Y> const& x)
+ : base (x), x_ (x.x_)
+ {
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ shared_ptr&
+ operator= (shared_ptr const& x)
+ {
+ if (x_ != x.x_)
+ {
+ if (x_ != 0)
+ base::dec (x_);
+
+ static_cast<base&> (*this) = x;
+ x_ = x.x_;
+
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ return *this;
+ }
+
+ template <typename Y>
+ shared_ptr&
+ operator= (shared_ptr<Y> const& x)
+ {
+ if (x_ != x.x_)
+ {
+ if (x_ != 0)
+ base::dec (x_);
+
+ static_cast<base&> (*this) = x;
+ x_ = x.x_;
+
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ return *this;
+ }
+
+ public:
+ X*
+ operator-> () const
+ {
+ return x_;
+ }
+
+ X&
+ operator* () const
+ {
+ return *x_;
+ }
+
+ // Conversion to bool.
+ //
+ typedef void (shared_ptr::*boolean_convertible)();
+ void true_value () {};
+
+ operator boolean_convertible () const
+ {
+ return x_ ? &shared_ptr<X>::true_value : 0;
+ }
+
+ public:
+ X*
+ get () const
+ {
+ return x_;
+ }
+
+ X*
+ release ()
+ {
+ X* r (x_);
+ x_ = 0;
+ return r;
+ }
+
+ std::size_t
+ count () const
+ {
+ return x_ != 0 ? base::count (x_) : 0;
+ }
+
+ private:
+ template <typename>
+ friend class shared_ptr;
+
+ X* x_;
+ };
+}
+
+#endif // CUTL_SHARED_PTR_HXX
diff --git a/cutl/shared-ptr/base.cxx b/cutl/shared-ptr/base.cxx
new file mode 100644
index 0000000..a74ed15
--- /dev/null
+++ b/cutl/shared-ptr/base.cxx
@@ -0,0 +1,63 @@
+// file : cutl/shared-ptr/base.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/shared-ptr/base.hxx>
+
+using std::size_t;
+
+//
+//
+cutl::share shared = cutl::share (1);
+cutl::share exclusive = cutl::share (2);
+
+//
+//
+namespace cutl
+{
+ char const* not_shared::
+ what () const throw ()
+ {
+ return "object is not shared";
+ }
+}
+
+//
+//
+void*
+operator new (size_t n, cutl::share s) throw (std::bad_alloc)
+{
+ if (s == shared)
+ {
+ // Here we need to make sure we don't break the alignment of the
+ // returned block. For that we need to know the maximum alignment
+ // of this platform. Twice the pointer size is a good guess for
+ // most platforms.
+ //
+ size_t* p = static_cast<size_t*> (operator new (n + 2 * sizeof (size_t)));
+ *p++ = 1; // Initial count.
+ *p++ = 0xDEADBEEF; // Signature.
+ return p;
+ }
+ else
+ return operator new (n);
+
+}
+
+void
+operator delete (void* p, cutl::share s) throw ()
+{
+ // This version of operator delete is only called when the c-tor
+ // fails. In this case there is no object and we can just free the
+ // memory.
+ //
+ if (s == shared)
+ {
+ size_t* sp = static_cast<size_t*> (p);
+ sp -= 2;
+ operator delete (sp);
+ }
+ else
+ operator delete (p);
+}
diff --git a/cutl/shared-ptr/base.hxx b/cutl/shared-ptr/base.hxx
new file mode 100644
index 0000000..bb297cb
--- /dev/null
+++ b/cutl/shared-ptr/base.hxx
@@ -0,0 +1,90 @@
+// file : cutl/shared-ptr/base.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_SHARED_PTR_BASE_HXX
+#define CUTL_SHARED_PTR_BASE_HXX
+
+#include <new>
+#include <cstddef> // std::size_t
+#include <exception> // std::exception
+
+namespace cutl
+{
+ struct share
+ {
+ explicit
+ share (char id);
+
+ bool
+ operator== (share) const;
+
+ private:
+ char id_;
+ };
+}
+
+extern cutl::share shared;
+extern cutl::share exclusive;
+
+void*
+operator new (std::size_t, cutl::share) throw (std::bad_alloc);
+
+void
+operator delete (void*, cutl::share) throw ();
+
+namespace cutl
+{
+ struct not_shared: std::exception
+ {
+ virtual char const*
+ what () const throw ();
+ };
+
+ struct shared_base
+ {
+ shared_base ();
+ shared_base (shared_base const&);
+ shared_base&
+ operator= (shared_base const&);
+
+ void
+ _inc_ref ();
+
+ bool
+ _dec_ref ();
+
+ std::size_t
+ _ref_count () const;
+
+ void*
+ operator new (std::size_t, share) throw (std::bad_alloc);
+
+ void
+ operator delete (void*, share) throw ();
+
+ void
+ operator delete (void*) throw ();
+
+ protected:
+ std::size_t counter_;
+ };
+
+ template <typename X>
+ inline X*
+ inc_ref (X*);
+
+ template <typename X>
+ inline void
+ dec_ref (X*);
+
+ template <typename X>
+ inline std::size_t
+ ref_count (X const*);
+}
+
+#include <cutl/shared-ptr/base.ixx>
+#include <cutl/shared-ptr/base.txx>
+
+#endif // CUTL_SHARED_PTR_BASE_HXX
diff --git a/cutl/shared-ptr/base.ixx b/cutl/shared-ptr/base.ixx
new file mode 100644
index 0000000..928e439
--- /dev/null
+++ b/cutl/shared-ptr/base.ixx
@@ -0,0 +1,79 @@
+// file : cutl/shared-ptr/base.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ // share
+ //
+
+ inline share::
+ share (char id)
+ : id_ (id)
+ {
+ }
+
+ inline bool share::
+ operator== (share x) const
+ {
+ return id_ == x.id_;
+ }
+
+ // shared_base
+ //
+
+ inline shared_base::
+ shared_base ()
+ : counter_ (1)
+ {
+ }
+
+ inline shared_base::
+ shared_base (shared_base const&)
+ : counter_ (1)
+ {
+ }
+
+ inline shared_base& shared_base::
+ operator= (shared_base const&)
+ {
+ return *this;
+ }
+
+ inline void shared_base::
+ _inc_ref ()
+ {
+ counter_++;
+ }
+
+ inline bool shared_base::
+ _dec_ref ()
+ {
+ return --counter_ == 0;
+ }
+
+ inline std::size_t shared_base::
+ _ref_count () const
+ {
+ return counter_;
+ }
+
+ inline void* shared_base::
+ operator new (std::size_t n, share) throw (std::bad_alloc)
+ {
+ return ::operator new (n);
+ }
+
+ inline void shared_base::
+ operator delete (void* p, share) throw ()
+ {
+ ::operator delete (p);
+ }
+
+ inline void shared_base::
+ operator delete (void* p) throw ()
+ {
+ ::operator delete (p);
+ }
+}
diff --git a/cutl/shared-ptr/base.txx b/cutl/shared-ptr/base.txx
new file mode 100644
index 0000000..168fb52
--- /dev/null
+++ b/cutl/shared-ptr/base.txx
@@ -0,0 +1,174 @@
+// file : cutl/shared-ptr/base.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/meta/answer.hxx>
+#include <cutl/meta/polymorphic-p.hxx>
+
+namespace cutl
+{
+ namespace bits
+ {
+ // Support for locating the counter in the memory block.
+ //
+ template <typename X, bool poly = meta::polymorphic_p<X>::r>
+ struct locator;
+
+ template <typename X>
+ struct locator<X, false>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (reinterpret_cast<std::size_t*> (x));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ struct locator<X, true>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (
+ static_cast<std::size_t*> (
+ dynamic_cast<void*> (x)));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ std::size_t*
+ counter (X const* p)
+ {
+ return bits::locator<X>::counter (const_cast<X*> (p));
+ }
+
+ // Counter type and operations.
+ //
+ meta::no test (...);
+ meta::yes test (shared_base*);
+
+ template <typename X,
+ std::size_t A = sizeof (test (reinterpret_cast<X*> (0)))>
+ struct counter_type;
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::no)>
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::yes)>
+ {
+ typedef shared_base r;
+ };
+
+ template <typename X, typename Y>
+ struct counter_ops;
+
+ template <typename X>
+ struct counter_ops<X, X>
+ {
+ counter_ops (X const* p) : counter_ (p ? bits::counter (p) : 0) {}
+ counter_ops (counter_ops const& x) : counter_ (x.counter_) {}
+
+ template <typename Y>
+ counter_ops (counter_ops<Y, Y> const& x) : counter_ (x.counter_) {}
+
+ counter_ops&
+ operator= (counter_ops const& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ template <typename Y>
+ counter_ops&
+ operator= (counter_ops<Y, Y> const& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ void
+ inc (X*)
+ {
+ (*counter_)++;
+ }
+
+ void
+ dec (X* p)
+ {
+ if (--(*counter_) == 0)
+ {
+ p->~X ();
+ operator delete (counter_); // Counter is the top of the memory block.
+ }
+ }
+
+ std::size_t
+ count (X const*) const
+ {
+ return *counter_;
+ }
+
+ std::size_t* counter_;
+ };
+
+ template <typename Y>
+ struct counter_ops<shared_base, Y>
+ {
+ counter_ops (Y const*) {}
+
+ void
+ inc (shared_base* p) {p->_inc_ref ();}
+
+ void
+ dec (Y* p)
+ {
+ if (static_cast<shared_base*> (p)->_dec_ref ())
+ delete p;
+ }
+
+ std::size_t
+ count (shared_base const* p) const {return p->_ref_count ();}
+ };
+ }
+
+ template <typename X>
+ inline X*
+ inc_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.inc (p);
+ return p;
+ }
+
+ template <typename X>
+ inline void
+ dec_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.dec (p);
+ }
+
+ template <typename X>
+ inline std::size_t
+ ref_count (X const* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ return c.count (p);
+ }
+}
diff --git a/cutl/static-ptr.hxx b/cutl/static-ptr.hxx
new file mode 100644
index 0000000..12ecc1c
--- /dev/null
+++ b/cutl/static-ptr.hxx
@@ -0,0 +1,75 @@
+// file : cutl/static-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_STATIC_PTR_HXX
+#define CUTL_STATIC_PTR_HXX
+
+#include <cstddef> // std::size_t
+
+namespace cutl
+{
+ // This class template implements Jerry Schwarz's static
+ // initialization technique commonly found in iostream
+ // implementations.
+ //
+ // The second template argument is used to make sure the
+ // instantiation of static_ptr is unique.
+ //
+ template <typename X, typename ID>
+ class static_ptr
+ {
+ public:
+ static_ptr ()
+ {
+ if (count_ == 0)
+ x_ = new X;
+
+ ++count_;
+ }
+
+ ~static_ptr ()
+ {
+ if (--count_ == 0)
+ delete x_;
+ }
+
+ private:
+ static_ptr (static_ptr const&);
+
+ static_ptr&
+ operator= (static_ptr const&);
+
+ public:
+ X*
+ operator-> () const
+ {
+ return x_;
+ }
+
+ X&
+ operator* () const
+ {
+ return *x_;
+ }
+
+ X*
+ get () const
+ {
+ return x_;
+ }
+
+ private:
+ static X* x_;
+ static std::size_t count_;
+ };
+
+ template <typename X, typename ID>
+ X* static_ptr<X, ID>::x_ = 0;
+
+ template <typename X, typename ID>
+ std::size_t static_ptr<X, ID>::count_ = 0;
+}
+
+#endif // CUTL_STATIC_PTR_HXX
diff --git a/doc/components.txt b/doc/components.txt
new file mode 100644
index 0000000..cdb1920
--- /dev/null
+++ b/doc/components.txt
@@ -0,0 +1,6 @@
+Components
+
+ core: meta/ shared-ptr/ shared-ptr.hxx
+ container: container/
+ compiler: compiler/
+
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..5d90ad8
--- /dev/null
+++ b/makefile
@@ -0,0 +1,42 @@
+# file : makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make
+
+default := $(out_base)/
+test := $(out_base)/.test
+install := $(out_base)/.install
+dist := $(out_base)/.dist
+clean := $(out_base)/.clean
+
+# Build.
+#
+$(default): $(out_base)/cutl/ $(out_base)/tests/
+
+# Test.
+#
+$(test): $(out_base)/tests/.test
+
+# Install.
+#
+$(install): $(out_base)/cutl/.install \
+ $(out_base)/doc/.install
+ $(call install-data,$(src_base)/LICENSE,$(install_doc_dir)/libcutl/LICENSE)
+ $(call install-data,$(src_base)/NEWS,$(install_doc_dir)/libcutl/NEWS)
+ $(call install-data,$(src_base)/README,$(install_doc_dir)/libcutl/README)
+
+# Dist.
+#
+
+# @@ TODO
+
+# Clean.
+#
+$(clean): $(out_base)/cutl/.clean $(out_base)/tests/.clean
+
+$(call include,$(bld_root)/install.make)
+
+$(call import,$(src_base)/cutl/makefile)
+$(call import,$(src_base)/tests/makefile)
diff --git a/tests/compiler/makefile b/tests/compiler/makefile
new file mode 100644
index 0000000..5a63fc8
--- /dev/null
+++ b/tests/compiler/makefile
@@ -0,0 +1,18 @@
+# file : tests/compiler/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+tests := traversal
+
+default := $(out_base)/
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests)))
+$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests)))
+$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests)))
+
+$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile))
diff --git a/tests/compiler/traversal/driver.cxx b/tests/compiler/traversal/driver.cxx
new file mode 100644
index 0000000..8d49b6f
--- /dev/null
+++ b/tests/compiler/traversal/driver.cxx
@@ -0,0 +1,135 @@
+// file : tests/compiler/traversal/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <vector>
+#include <iostream>
+
+#include <cutl/shared-ptr.hxx>
+
+#include <cutl/compiler/type-info.hxx>
+#include <cutl/compiler/traversal.hxx>
+
+using namespace std;
+using namespace cutl;
+
+// Data types.
+//
+struct base
+{
+ virtual ~base () {}
+};
+
+struct derived1: base {};
+struct derived2: base {};
+
+typedef vector<shared_ptr<base> > objects;
+
+struct init
+{
+ init ()
+ {
+ using compiler::type_info;
+
+ {
+ type_info ti (typeid (base));
+ insert (ti);
+ }
+
+ {
+ type_info ti (typeid (derived1));
+ ti.add_base (typeid (base));
+ insert (ti);
+ }
+
+ {
+ type_info ti (typeid (derived2));
+ ti.add_base (typeid (base));
+ insert (ti);
+ }
+ }
+} init_;
+
+// Traversers.
+//
+template <typename X>
+struct traverser: compiler::traverser_impl<X, base>,
+ virtual compiler::dispatcher<base>
+{
+};
+
+typedef traverser<base> base_trav;
+typedef traverser<derived1> derived1_trav;
+typedef traverser<derived2> derived2_trav;
+
+struct base_impl: base_trav
+{
+ virtual void
+ traverse (type&)
+ {
+ cout << "base_impl: base" << endl;
+ }
+};
+
+struct derived1_impl: derived1_trav
+{
+ virtual void
+ traverse (type&)
+ {
+ cout << "derived1_impl: derived1" << endl;
+ }
+};
+
+struct combined_impl: derived1_trav, derived2_trav
+{
+ virtual void
+ traverse (derived1&)
+ {
+ cout << "combined_impl: derived1" << endl;
+ }
+
+ virtual void
+ traverse (derived2&)
+ {
+ cout << "combined_impl: derived2" << endl;
+ }
+};
+
+int
+main ()
+{
+ objects o;
+ o.push_back (shared_ptr<base> (new (shared) base));
+ o.push_back (shared_ptr<base> (new (shared) derived1));
+ o.push_back (shared_ptr<base> (new (shared) derived2));
+
+ base_impl base;
+ derived1_impl derived1;
+ combined_impl combined;
+
+ for (objects::iterator i (o.begin ()); i != o.end (); ++i)
+ base.dispatch (**i);
+
+ cout << endl;
+
+ for (objects::iterator i (o.begin ()); i != o.end (); ++i)
+ derived1.dispatch (**i);
+
+ cout << endl;
+
+ for (objects::iterator i (o.begin ()); i != o.end (); ++i)
+ combined.dispatch (**i);
+
+ cout << endl;
+
+ base.traverser (derived1);
+ for (objects::iterator i (o.begin ()); i != o.end (); ++i)
+ base.dispatch (**i);
+
+ cout << endl;
+
+ derived1.traverser (combined);
+ for (objects::iterator i (o.begin ()); i != o.end (); ++i)
+ derived1.dispatch (**i);
+}
diff --git a/tests/compiler/traversal/makefile b/tests/compiler/traversal/makefile
new file mode 100644
index 0000000..bb5513a
--- /dev/null
+++ b/tests/compiler/traversal/makefile
@@ -0,0 +1,71 @@
+# file : tests/compiler/traversal/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := driver.cxx
+
+#
+#
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cutl.l := $(out_root)/cutl/cutl.l
+cutl.l.cpp-options := $(out_root)/cutl/cutl.l.cpp-options
+
+driver := $(out_base)/driver
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+# Build.
+#
+$(driver): $(cxx_obj) $(cutl.l)
+$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options)
+
+
+$(call include-dep,$(cxx_od))
+
+
+# Alias for default target.
+#
+$(out_base)/: $(driver)
+
+
+# Test.
+#
+$(test): driver := $(driver)
+$(test): $(driver) $(src_base)/output.std
+ $(call message,test $$1,$$1 | diff -u $(src_base)/output.std -,$(driver))
+
+
+# Clean.
+#
+$(clean): \
+ $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cutl/makefile)
diff --git a/tests/compiler/traversal/output.std b/tests/compiler/traversal/output.std
new file mode 100644
index 0000000..095739c
--- /dev/null
+++ b/tests/compiler/traversal/output.std
@@ -0,0 +1,16 @@
+base_impl: base
+base_impl: base
+base_impl: base
+
+derived1_impl: derived1
+
+combined_impl: derived1
+combined_impl: derived2
+
+base_impl: base
+derived1_impl: derived1
+base_impl: base
+
+derived1_impl: derived1
+combined_impl: derived1
+combined_impl: derived2
diff --git a/tests/makefile b/tests/makefile
new file mode 100644
index 0000000..ffbd8bd
--- /dev/null
+++ b/tests/makefile
@@ -0,0 +1,18 @@
+# file : tests/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+tests := compiler shared-ptr
+
+default := $(out_base)/
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests)))
+$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests)))
+$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests)))
+
+$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile))
diff --git a/tests/shared-ptr/driver.cxx b/tests/shared-ptr/driver.cxx
new file mode 100644
index 0000000..c32192e
--- /dev/null
+++ b/tests/shared-ptr/driver.cxx
@@ -0,0 +1,186 @@
+// file : tests/shared-ptr/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <string>
+#include <cassert>
+
+#include <cutl/shared-ptr.hxx>
+
+using namespace cutl;
+
+struct type
+{
+ type (int x, char const* y) : x_ (x), y_ (y) {}
+
+ int x_;
+ std::string y_;
+};
+
+struct base1
+{
+ virtual
+ ~base1 () {}
+ base1 (int x) : x_ (x) {}
+
+ int x_;
+};
+
+struct base2
+{
+ virtual
+ ~base2 () {}
+ base2 (char const* y) : y_ (y) {}
+
+ std::string y_;
+};
+
+struct derived: base1, base2
+{
+ derived (int x, char const* y) : base1 (x), base2 (y) {}
+};
+
+struct shared_type: shared_base
+{
+ shared_type (int x, char const* y)
+ : x_ (x), y_ (y)
+ {
+ assert (ref_count (this) == 1);
+ }
+
+ int x_;
+ std::string y_;
+};
+
+int
+main ()
+{
+ //
+ // inc_ref, dec_ref, ref_count
+ //
+
+ // Non-polymorphic type.
+ //
+ {
+ type* x (new (shared) type (5, "foo"));
+ assert (ref_count (x) == 1);
+ inc_ref (x);
+ assert (ref_count (x) == 2);
+ dec_ref (x);
+ assert (ref_count (x) == 1);
+ dec_ref (x);
+ }
+
+ // Polymorphic type.
+ //
+ {
+ base2* x (new (shared) derived (5, "foo"));
+ assert (ref_count (x) == 1);
+ inc_ref (x);
+ assert (ref_count (x) == 2);
+ dec_ref (x);
+ assert (ref_count (x) == 1);
+ dec_ref (x);
+ }
+
+ // Shared type.
+ //
+ {
+ shared_type* x (new (shared) shared_type (5, "foo"));
+ assert (ref_count (x) == 1);
+ inc_ref (x);
+ assert (ref_count (x) == 2);
+ dec_ref (x);
+ assert (ref_count (x) == 1);
+ dec_ref (x);
+ }
+
+ // Error handling (this theoretically can segfault).
+ //
+ {
+ type* x (new type (5, "foo"));
+
+ try
+ {
+ inc_ref (x);
+ assert (false);
+ }
+ catch (not_shared const&)
+ {
+ }
+
+ delete x;
+ }
+
+ //
+ // shared_ptr
+ //
+
+ // Non-polymorphic type.
+ //
+ {
+ shared_ptr<type> x (new (shared) type (5, "foo"));
+ assert (x.count () == 1);
+ assert (x);
+ assert (x->x_ == 5);
+ assert ((*x).y_ == "foo");
+ {
+ shared_ptr<type> y (x);
+ assert (y.count () == 2);
+ }
+ {
+ shared_ptr<type> y;
+ y = x;
+ assert (y.count () == 2);
+ }
+ assert (x.count () == 1);
+ shared_ptr<type> y (x.release ());
+ assert (y.count () == 1);
+ }
+
+ // Polymorphic type.
+ //
+ {
+ shared_ptr<derived> x (new (shared) derived (5, "foo"));
+ assert (x.count () == 1);
+ {
+ shared_ptr<base2> y (x);
+ assert (y.count () == 2);
+ assert (y->y_ == "foo");
+ }
+ {
+ shared_ptr<base2> y;
+ y = x;
+ assert (y.count () == 2);
+ }
+ assert (x.count () == 1);
+ }
+
+ // Non-polymorphic type.
+ //
+ {
+ shared_ptr<shared_type> x (new (shared) shared_type (5, "foo"));
+ assert (x.count () == 1);
+ assert (x);
+ assert (x->x_ == 5);
+ assert ((*x).y_ == "foo");
+ assert (x->_ref_count () == 1);
+ x->_inc_ref ();
+ assert (x.count () == 2);
+ x->_dec_ref ();
+ assert (x.count () == 1);
+ {
+ shared_ptr<shared_type> y (x);
+ assert (y.count () == 2);
+ }
+ {
+ shared_ptr<shared_type> y;
+ y = x;
+ assert (y.count () == 2);
+ }
+ assert (x.count () == 1);
+ shared_ptr<shared_type> y (x.release ());
+ assert (y.count () == 1);
+ }
+}
diff --git a/tests/shared-ptr/makefile b/tests/shared-ptr/makefile
new file mode 100644
index 0000000..43e9b53
--- /dev/null
+++ b/tests/shared-ptr/makefile
@@ -0,0 +1,70 @@
+# file : tests/shared-ptr/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+cxx_tun := driver.cxx
+
+#
+#
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cutl.l := $(out_root)/cutl/cutl.l
+cutl.l.cpp-options := $(out_root)/cutl/cutl.l.cpp-options
+
+driver := $(out_base)/driver
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+# Build.
+#
+$(driver): $(cxx_obj) $(cutl.l)
+$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options)
+
+
+$(call include-dep,$(cxx_od))
+
+
+# Alias for default target.
+#
+$(out_base)/: $(driver)
+
+
+# Test.
+#
+$(test): $(driver)
+ $(call message,test $<,$<)
+
+
+# Clean.
+#
+$(clean): \
+ $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cutl/makefile)
diff --git a/version b/version
new file mode 100644
index 0000000..3eefcb9
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+1.0.0