summaryrefslogtreecommitdiff
path: root/cli/cli/semantics
diff options
context:
space:
mode:
Diffstat (limited to 'cli/cli/semantics')
-rw-r--r--cli/cli/semantics/class.cxx39
-rw-r--r--cli/cli/semantics/class.hxx106
-rw-r--r--cli/cli/semantics/doc.cxx27
-rw-r--r--cli/cli/semantics/doc.hxx22
-rw-r--r--cli/cli/semantics/elements.cxx129
-rw-r--r--cli/cli/semantics/elements.hxx407
-rw-r--r--cli/cli/semantics/expression.cxx27
-rw-r--r--cli/cli/semantics/expression.hxx76
-rw-r--r--cli/cli/semantics/namespace.cxx27
-rw-r--r--cli/cli/semantics/namespace.hxx26
-rw-r--r--cli/cli/semantics/option.cxx47
-rw-r--r--cli/cli/semantics/option.hxx189
-rw-r--r--cli/cli/semantics/unit.cxx63
-rw-r--r--cli/cli/semantics/unit.hxx310
-rw-r--r--cli/cli/semantics/unit.txx108
15 files changed, 1603 insertions, 0 deletions
diff --git a/cli/cli/semantics/class.cxx b/cli/cli/semantics/class.cxx
new file mode 100644
index 0000000..494d5d0
--- /dev/null
+++ b/cli/cli/semantics/class.cxx
@@ -0,0 +1,39 @@
+// file : cli/semantics/class.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/class.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // inherits
+ //
+ {
+ type_info ti (typeid (inherits));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // class_
+ //
+ {
+ type_info ti (typeid (class_));
+ ti.add_base (typeid (scope));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/class.hxx b/cli/cli/semantics/class.hxx
new file mode 100644
index 0000000..ca7de8c
--- /dev/null
+++ b/cli/cli/semantics/class.hxx
@@ -0,0 +1,106 @@
+// file : cli/semantics/class.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_CLASS_HXX
+#define CLI_SEMANTICS_CLASS_HXX
+
+#include <vector>
+
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ class class_;
+
+ class inherits: public edge
+ {
+ public:
+ class_&
+ base () const
+ {
+ return *base_;
+ }
+
+ class_&
+ derived () const
+ {
+ return *derived_;
+ }
+
+ public:
+ void
+ set_left_node (class_& n)
+ {
+ derived_ = &n;
+ }
+
+ void
+ set_right_node (class_& n)
+ {
+ base_ = &n;
+ }
+
+ protected:
+ class_* base_;
+ class_* derived_;
+ };
+
+ class class_: public scope
+ {
+ private:
+ typedef std::vector<inherits*> inherits_list;
+
+ public:
+ bool
+ abstract () const
+ {
+ return abstract_;
+ }
+
+ void
+ abstract (bool a)
+ {
+ abstract_ = a;
+ }
+
+ public:
+ typedef pointer_iterator<inherits_list::const_iterator> inherits_iterator;
+
+ inherits_iterator
+ inherits_begin () const
+ {
+ return inherits_.begin ();
+ }
+
+ inherits_iterator
+ inherits_end () const
+ {
+ return inherits_.end ();
+ }
+
+ public:
+ class_ (path const& file, size_t line, size_t column)
+ : node (file, line, column), abstract_ (false)
+ {
+ }
+
+ void
+ add_edge_left (inherits& e)
+ {
+ inherits_.push_back (&e);
+ }
+
+ void
+ add_edge_right (inherits&) {}
+
+ using scope::add_edge_left;
+ using scope::add_edge_right;
+
+ private:
+ bool abstract_;
+ inherits_list inherits_;
+ };
+}
+
+#endif // CLI_SEMANTICS_CLASS_HXX
diff --git a/cli/cli/semantics/doc.cxx b/cli/cli/semantics/doc.cxx
new file mode 100644
index 0000000..c31260c
--- /dev/null
+++ b/cli/cli/semantics/doc.cxx
@@ -0,0 +1,27 @@
+// file : cli/semantics/doc.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/doc.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ type_info ti (typeid (doc));
+ ti.add_base (typeid (nameable));
+ insert (ti);
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/doc.hxx b/cli/cli/semantics/doc.hxx
new file mode 100644
index 0000000..8dacb7a
--- /dev/null
+++ b/cli/cli/semantics/doc.hxx
@@ -0,0 +1,22 @@
+// file : cli/semantics/doc.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_DOC_HXX
+#define CLI_SEMANTICS_DOC_HXX
+
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ // Scope-level documentation node.
+ //
+ class doc: public nameable, public doc_strings
+ {
+ public:
+ doc (path const& file, size_t line, size_t column)
+ : node (file, line, column) {}
+ };
+}
+
+#endif // CLI_SEMANTICS_DOC_HXX
diff --git a/cli/cli/semantics/elements.cxx b/cli/cli/semantics/elements.cxx
new file mode 100644
index 0000000..ed8eb7d
--- /dev/null
+++ b/cli/cli/semantics/elements.cxx
@@ -0,0 +1,129 @@
+// file : cli/semantics/elements.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ // nameable
+ //
+ string nameable::
+ fq_name () const
+ {
+ string const& n (name ());
+
+ if (n.empty ())
+ return n;
+ else
+ return scope ().fq_name () + "::" + n;
+ }
+
+ // scope
+ //
+
+ scope::names_iterator_pair scope::
+ find (string const& name) const
+ {
+ names_map::const_iterator i (names_map_.find (name));
+
+ if (i == names_map_.end ())
+ return names_iterator_pair (names_.end (), names_.end ());
+ else
+ return names_iterator_pair (i->second.begin (), i->second.end ());
+ }
+
+ scope::names_iterator scope::
+ find (names& e)
+ {
+ list_iterator_map::iterator i (iterator_map_.find (&e));
+ return i != iterator_map_.end () ? i->second : names_.end ();
+ }
+
+ void scope::
+ add_edge_left (names& e)
+ {
+ names_list::iterator it (names_.insert (names_.end (), &e));
+ iterator_map_[&e] = it;
+
+ for (names::name_iterator i (e.name_begin ()); i != e.name_end (); ++i)
+ names_map_[*i].push_back (&e);
+ }
+
+ void scope::
+ remove_edge_left (names& e)
+ {
+ list_iterator_map::iterator i (iterator_map_.find (&e));
+ assert (i != iterator_map_.end ());
+
+ names_.erase (i->second);
+ iterator_map_.erase (i);
+
+ for (names::name_iterator ni (e.name_begin ()); ni != e.name_end (); ++ni)
+ {
+ names_map::iterator j (names_map_.find (*ni));
+
+ for (names_list::iterator i (j->second.begin ());
+ i != j->second.end (); ++i)
+ {
+ if (*i == &e)
+ i = j->second.erase (i);
+ }
+ }
+ }
+
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // node
+ //
+ insert (type_info (typeid (node)));
+
+ // edge
+ //
+ insert (type_info (typeid (edge)));
+
+ // names
+ //
+ {
+ type_info ti (typeid (names));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // nameable
+ //
+ {
+ type_info ti (typeid (nameable));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+
+ // scope
+ //
+ {
+ type_info ti (typeid (scope));
+ ti.add_base (typeid (nameable));
+ insert (ti);
+ }
+
+ // type
+ //
+ {
+ type_info ti (typeid (type));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/elements.hxx b/cli/cli/semantics/elements.hxx
new file mode 100644
index 0000000..6235a06
--- /dev/null
+++ b/cli/cli/semantics/elements.hxx
@@ -0,0 +1,407 @@
+// file : cli/semantics/elements.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_ELEMENTS_HXX
+#define CLI_SEMANTICS_ELEMENTS_HXX
+
+#include <map>
+#include <list>
+#include <vector>
+#include <string>
+#include <cstddef> // std::size_t
+#include <cstdlib> // std::abort
+#include <utility> // std::pair
+#include <cassert>
+
+#include <cutl/fs/path.hxx>
+
+#include <cutl/container/graph.hxx>
+#include <cutl/container/pointer-iterator.hxx>
+
+#include <cutl/compiler/context.hxx>
+
+namespace semantics
+{
+ using namespace cutl;
+
+ using std::size_t;
+ using std::string;
+
+ using container::graph;
+ using container::pointer_iterator;
+
+ using compiler::context;
+
+
+ //
+ //
+ using fs::path;
+ using fs::invalid_path;
+
+ //
+ //
+ typedef std::vector<string> doc_strings;
+
+ //
+ //
+ class node;
+ class edge;
+
+
+ //
+ //
+ class edge
+ {
+ public:
+ virtual
+ ~edge () {}
+
+ public:
+ typedef semantics::context context_type;
+
+ context_type&
+ context ()
+ {
+ return context_;
+ }
+
+ public:
+ template <typename X>
+ bool
+ is_a () const
+ {
+ return dynamic_cast<X const*> (this) != 0;
+ }
+
+ private:
+ context_type context_;
+ };
+
+ //
+ //
+ class node
+ {
+ public:
+ virtual
+ ~node () {}
+
+ public:
+ typedef semantics::context context_type;
+
+ context_type&
+ context ()
+ {
+ return context_;
+ }
+
+ public:
+ path const&
+ file () const
+ {
+ return file_;
+ }
+
+ size_t
+ line () const
+ {
+ return line_;
+ }
+
+ size_t
+ column () const
+ {
+ return column_;
+ }
+
+ public:
+ template <typename X>
+ bool
+ is_a () const
+ {
+ return dynamic_cast<X const*> (this) != 0;
+ }
+
+ public:
+ node (path const& file, size_t line, size_t column)
+ : file_ (file), line_ (line), column_ (column)
+ {
+ }
+
+ // For virtual inheritance. Should never be actually called.
+ //
+ node ()
+ : file_ ("")
+ {
+ std::abort ();
+ }
+
+ // Sink functions that allow extensions in the form of one-way
+ // edges.
+ //
+ void
+ add_edge_right (edge&)
+ {
+ }
+
+ private:
+ context_type context_;
+ path file_;
+ size_t line_;
+ size_t column_;
+ };
+
+ //
+ //
+ class scope;
+ class nameable;
+
+
+ //
+ //
+ class names: public edge
+ {
+ public:
+ typedef semantics::scope scope_type;
+
+ typedef std::vector<string> name_list;
+ typedef name_list::const_iterator name_iterator;
+
+ // First name.
+ //
+ string const&
+ name () const
+ {
+ return names_[0];
+ }
+
+ name_iterator
+ name_begin () const
+ {
+ return names_.begin ();
+ }
+
+ name_iterator
+ name_end () const
+ {
+ return names_.end ();
+ }
+
+ scope_type&
+ scope () const
+ {
+ return *scope_;
+ }
+
+ nameable&
+ named () const
+ {
+ return *named_;
+ }
+
+ public:
+ names (string const& name)
+ {
+ names_.push_back (name);
+ }
+
+ names (name_list const& names)
+ : names_ (names)
+ {
+ }
+
+ void
+ set_left_node (scope_type& n)
+ {
+ scope_ = &n;
+ }
+
+ void
+ set_right_node (nameable& n)
+ {
+ named_ = &n;
+ }
+
+ void
+ clear_left_node (scope_type& n)
+ {
+ assert (scope_ == &n);
+ scope_ = 0;
+ }
+
+ void
+ clear_right_node (nameable& n)
+ {
+ assert (named_ == &n);
+ named_ = 0;
+ }
+
+ protected:
+ scope_type* scope_;
+ nameable* named_;
+ name_list names_;
+ };
+
+
+ //
+ //
+ class nameable: public virtual node
+ {
+ public:
+ typedef semantics::scope scope_type;
+
+ string
+ name () const
+ {
+ return named_->name ();
+ }
+
+ string
+ fq_name () const;
+
+ scope_type&
+ scope ()
+ {
+ return named_->scope ();
+ }
+
+ scope_type const&
+ scope () const
+ {
+ return named_->scope ();
+ }
+
+ names&
+ named ()
+ {
+ return *named_;
+ }
+
+ public:
+ nameable ()
+ : named_ (0)
+ {
+ }
+
+ void
+ add_edge_right (names& e)
+ {
+ assert (named_ == 0);
+ named_ = &e;
+ }
+
+ void
+ remove_edge_right (names& e)
+ {
+ assert (named_ == &e);
+ named_ = 0;
+ }
+
+ using node::add_edge_right;
+
+ private:
+ names* named_;
+ };
+
+
+ //
+ //
+ class scope: public virtual nameable
+ {
+ protected:
+ typedef std::list<names*> names_list;
+ typedef std::map<names*, names_list::iterator> list_iterator_map;
+ typedef std::map<string, names_list> names_map;
+
+ public:
+ typedef pointer_iterator<names_list::iterator> names_iterator;
+ typedef pointer_iterator<names_list::const_iterator> names_const_iterator;
+
+ typedef
+ std::pair<names_const_iterator, names_const_iterator>
+ names_iterator_pair;
+
+ public:
+ names_iterator
+ names_begin ()
+ {
+ return names_.begin ();
+ }
+
+ names_iterator
+ names_end ()
+ {
+ return names_.end ();
+ }
+
+ names_const_iterator
+ names_begin () const
+ {
+ return names_.begin ();
+ }
+
+ names_const_iterator
+ names_end () const
+ {
+ return names_.end ();
+ }
+
+ bool
+ names_empty () const
+ {
+ return names_.empty ();
+ }
+
+ virtual names_iterator_pair
+ find (string const& name) const;
+
+ names_iterator
+ find (names&);
+
+ public:
+ scope (path const& file, size_t line, size_t column)
+ : node (file, line, column)
+ {
+ }
+
+ scope ()
+ {
+ }
+
+ void
+ add_edge_left (names&);
+
+ void
+ remove_edge_left (names&);
+
+ using nameable::add_edge_right;
+
+ private:
+ names_list names_;
+ list_iterator_map iterator_map_;
+ names_map names_map_;
+ };
+
+ //
+ //
+ class type: public node
+ {
+ public:
+ string const&
+ name () const
+ {
+ return name_;
+ }
+
+ public:
+ type (path const& file, size_t line, size_t column, string const& name)
+ : node (file, line, column), name_ (name)
+ {
+ }
+
+ private:
+ string name_;
+ };
+}
+
+#endif // CLI_SEMANTICS_ELEMENTS_HXX
diff --git a/cli/cli/semantics/expression.cxx b/cli/cli/semantics/expression.cxx
new file mode 100644
index 0000000..18d3312
--- /dev/null
+++ b/cli/cli/semantics/expression.cxx
@@ -0,0 +1,27 @@
+// file : cli/semantics/expression.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/expression.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ type_info ti (typeid (expression));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/expression.hxx b/cli/cli/semantics/expression.hxx
new file mode 100644
index 0000000..e36a0cb
--- /dev/null
+++ b/cli/cli/semantics/expression.hxx
@@ -0,0 +1,76 @@
+// file : cli/semantics/expression.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_EXPRESSION_HXX
+#define CLI_SEMANTICS_EXPRESSION_HXX
+
+#include <string>
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ //
+ //
+ class initialized;
+
+ //
+ //
+ class expression: public node
+ {
+ public:
+ enum expression_type
+ {
+ string_lit,
+ char_lit,
+ bool_lit,
+ int_lit,
+ float_lit,
+ call_expr,
+ identifier
+ };
+
+ expression_type
+ type () const
+ {
+ return type_;
+ }
+
+ std::string const&
+ value () const
+ {
+ return value_;
+ }
+
+ public:
+ initialized&
+ initializes () const
+ {
+ return *initializes_;
+ }
+
+ public:
+ expression (path const& file,
+ size_t line,
+ size_t column,
+ expression_type type,
+ std::string const& value)
+ : node (file, line, column), type_ (type), value_ (value)
+ {
+ }
+
+ void
+ add_edge_right (initialized& e)
+ {
+ initializes_ = &e;
+ }
+
+ private:
+ initialized* initializes_;
+
+ expression_type type_;
+ std::string value_;
+ };
+}
+
+#endif // CLI_SEMANTICS_EXPRESSION_HXX
diff --git a/cli/cli/semantics/namespace.cxx b/cli/cli/semantics/namespace.cxx
new file mode 100644
index 0000000..3c2643c
--- /dev/null
+++ b/cli/cli/semantics/namespace.cxx
@@ -0,0 +1,27 @@
+// file : cli/semantics/namespace.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/namespace.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ type_info ti (typeid (namespace_));
+ ti.add_base (typeid (scope));
+ insert (ti);
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/namespace.hxx b/cli/cli/semantics/namespace.hxx
new file mode 100644
index 0000000..00c7bfc
--- /dev/null
+++ b/cli/cli/semantics/namespace.hxx
@@ -0,0 +1,26 @@
+// file : cli/semantics/namespace.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_NAMESPACE_HXX
+#define CLI_SEMANTICS_NAMESPACE_HXX
+
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ class namespace_: public scope
+ {
+ public:
+ namespace_ (path const& file, size_t line, size_t column)
+ : node (file, line, column)
+ {
+ }
+
+ namespace_ ()
+ {
+ }
+ };
+}
+
+#endif // CLI_SEMANTICS_NAMESPACE_HXX
diff --git a/cli/cli/semantics/option.cxx b/cli/cli/semantics/option.cxx
new file mode 100644
index 0000000..8746a5e
--- /dev/null
+++ b/cli/cli/semantics/option.cxx
@@ -0,0 +1,47 @@
+// file : cli/semantics/option.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/option.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // belongs
+ //
+ {
+ type_info ti (typeid (belongs));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // initializes
+ //
+ {
+ type_info ti (typeid (initialized));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // option
+ //
+ {
+ type_info ti (typeid (option));
+ ti.add_base (typeid (nameable));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/option.hxx b/cli/cli/semantics/option.hxx
new file mode 100644
index 0000000..a9bb963
--- /dev/null
+++ b/cli/cli/semantics/option.hxx
@@ -0,0 +1,189 @@
+// file : cli/semantics/option.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_OPTION_HXX
+#define CLI_SEMANTICS_OPTION_HXX
+
+#include <cli/semantics/elements.hxx>
+
+namespace semantics
+{
+ //
+ //
+ class option;
+
+ //
+ //
+ class belongs: public edge
+ {
+ public:
+ typedef semantics::type type_type;
+ typedef semantics::option option_type;
+
+ option_type&
+ option () const
+ {
+ return *option_;
+ }
+
+ type_type&
+ type () const
+ {
+ return *type_;
+ }
+
+ public:
+ void
+ set_left_node (option_type& n)
+ {
+ option_ = &n;
+ }
+
+ void
+ set_right_node (type_type& n)
+ {
+ type_ = &n;
+ }
+
+ private:
+ option_type* option_;
+ type_type* type_;
+ };
+
+ //
+ //
+ class expression;
+
+ //
+ //
+ class initialized: public edge
+ {
+ public:
+ typedef semantics::option option_type;
+ typedef semantics::expression expression_type;
+
+ option_type&
+ option () const
+ {
+ return *option_;
+ }
+
+ expression_type&
+ expression () const
+ {
+ return *expression_;
+ }
+
+ public:
+ void
+ set_left_node (option_type& n)
+ {
+ option_ = &n;
+ }
+
+ void
+ set_right_node (expression_type& n)
+ {
+ expression_ = &n;
+ }
+
+ private:
+ option_type* option_;
+ expression_type* expression_;
+ };
+
+ //
+ //
+ class option: public nameable
+ {
+ public:
+ typedef semantics::belongs belongs_type;
+ typedef semantics::type type_type;
+
+ belongs_type&
+ belongs () const
+ {
+ return *belongs_;
+ }
+
+ type_type&
+ type () const
+ {
+ return belongs_->type ();
+ }
+
+ public:
+ typedef semantics::initialized initialized_type;
+
+ bool
+ initialized_p () const
+ {
+ return initialized_ != 0;
+ }
+
+ initialized_type&
+ initialized () const
+ {
+ return *initialized_;
+ }
+
+ expression&
+ initializer () const
+ {
+ return initialized_->expression ();
+ }
+
+ public:
+ typedef doc_strings::const_iterator doc_iterator;
+
+ doc_iterator
+ doc_begin () const
+ {
+ return doc_.begin ();
+ }
+
+ doc_iterator
+ doc_end () const
+ {
+ return doc_.end ();
+ }
+
+ doc_strings const&
+ doc () const
+ {
+ return doc_;
+ }
+
+ doc_strings&
+ doc ()
+ {
+ return doc_;
+ }
+
+ public:
+ option (path const& file, size_t line, size_t column)
+ : node (file, line, column), initialized_ (0)
+ {
+ }
+
+ void
+ add_edge_left (belongs_type& e)
+ {
+ belongs_ = &e;
+ }
+
+ void
+ add_edge_left (initialized_type& e)
+ {
+ initialized_ = &e;
+ }
+
+ private:
+ belongs_type* belongs_;
+ initialized_type* initialized_;
+ doc_strings doc_;
+ };
+}
+
+#endif // CLI_SEMANTICS_OPTION_HXX
diff --git a/cli/cli/semantics/unit.cxx b/cli/cli/semantics/unit.cxx
new file mode 100644
index 0000000..9c532ea
--- /dev/null
+++ b/cli/cli/semantics/unit.cxx
@@ -0,0 +1,63 @@
+// file : cli/semantics/unit.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+#include <cli/semantics/unit.hxx>
+
+namespace semantics
+{
+ // type info
+ //
+ namespace
+ {
+ struct init
+ {
+ init ()
+ {
+ using compiler::type_info;
+
+ // includes
+ //
+ {
+ type_info ti (typeid (includes));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
+ // cxx_includes
+ //
+ {
+ type_info ti (typeid (cxx_includes));
+ ti.add_base (typeid (includes));
+ insert (ti);
+ }
+
+ // cli_includes
+ //
+ {
+ type_info ti (typeid (cli_includes));
+ ti.add_base (typeid (includes));
+ insert (ti);
+ }
+
+ // cxx_unit
+ //
+ {
+ type_info ti (typeid (cxx_unit));
+ ti.add_base (typeid (node));
+ insert (ti);
+ }
+
+ // cli_unit
+ //
+ {
+ type_info ti (typeid (cli_unit));
+ ti.add_base (typeid (namespace_));
+ insert (ti);
+ }
+ }
+ } init_;
+ }
+}
diff --git a/cli/cli/semantics/unit.hxx b/cli/cli/semantics/unit.hxx
new file mode 100644
index 0000000..e37648a
--- /dev/null
+++ b/cli/cli/semantics/unit.hxx
@@ -0,0 +1,310 @@
+// file : cli/semantics/unit.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_SEMANTICS_UNIT_HXX
+#define CLI_SEMANTICS_UNIT_HXX
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <cli/semantics/elements.hxx>
+#include <cli/semantics/namespace.hxx>
+
+namespace semantics
+{
+ //
+ //
+ class cli_unit;
+ class cxx_unit;
+
+ //
+ //
+ class includes: public edge
+ {
+ public:
+ enum kind_type {quote, bracket};
+
+ cli_unit&
+ includer () const
+ {
+ return *includer_;
+ }
+
+ kind_type
+ kind () const
+ {
+ return kind_;
+ }
+
+ path const&
+ file () const
+ {
+ return file_;
+ }
+
+ public:
+ includes (kind_type kind, path const& file)
+ : kind_ (kind), file_ (file)
+ {
+ }
+
+ void
+ set_left_node (cli_unit& n)
+ {
+ includer_ = &n;
+ }
+
+ protected:
+ kind_type kind_;
+ path file_;
+ cli_unit* includer_;
+ };
+
+ //
+ //
+ class cli_includes: public includes
+ {
+ public:
+ cli_unit&
+ includee () const
+ {
+ return *includee_;
+ }
+
+ public:
+ cli_includes (kind_type kind, path const& file)
+ : includes (kind, file)
+ {
+ }
+
+ void
+ set_right_node (cli_unit& n)
+ {
+ includee_ = &n;
+ }
+
+ private:
+ cli_unit* includee_;
+ };
+
+ //
+ //
+ class cxx_includes: public includes
+ {
+ public:
+ cxx_unit&
+ includee () const
+ {
+ return *includee_;
+ }
+
+ public:
+ cxx_includes (kind_type kind, path const& file)
+ : includes (kind, file)
+ {
+ }
+
+ void
+ set_right_node (cxx_unit& n)
+ {
+ includee_ = &n;
+ }
+
+ private:
+ cxx_unit* includee_;
+ };
+
+ //
+ //
+ class cxx_unit: public node
+ {
+ public:
+ cxx_unit (path const& file, size_t line, size_t column)
+ : node (file, line, column)
+ {
+ }
+
+ void
+ add_edge_right (cxx_includes&)
+ {
+ }
+ };
+
+ //
+ //
+ class cli_unit: public graph<node, edge>, public namespace_
+ {
+ typedef std::vector<includes*> includes_list;
+
+ public:
+ // Lookup a name in the specified starting scope. Empty scope denotes
+ // the global namespace. Starting scope should be a fully-qualified
+ // name while name can be qualified but should not be fully-qualified
+ // (to lookup a fully-qualified name use the global namespace as the
+ // starting scope).
+ //
+ // The lookup starts in this unit and continues in all the units that
+ // this unit includes, transitively.
+ //
+ // The outer flag specifies whether to search the outer scopes.
+ //
+ template <typename T>
+ T*
+ lookup (std::string const& scope,
+ std::string const& name,
+ bool outer = true);
+
+ public:
+ typedef
+ pointer_iterator<includes_list::const_iterator>
+ includes_iterator;
+
+ includes_iterator
+ includes_begin () const
+ {
+ return includes_.begin ();
+ }
+
+ includes_iterator
+ includes_end () const
+ {
+ return includes_.end ();
+ }
+
+ public:
+ cli_unit (path const& file, size_t line, size_t column)
+ : node (file, line, column), graph_ (*this)
+ {
+ // Use a special edge to get this->name() return the global
+ // namespace name ("").
+ //
+ new_edge<global_names> (*this, *this);
+ }
+
+ public:
+ template <typename T>
+ T&
+ new_node (path const& file, size_t line, size_t column)
+ {
+ return graph_.new_node<T> (file, line, column);
+ }
+
+ template <typename T, typename A0>
+ T&
+ new_node (path const& file, size_t line, size_t column, A0 const& a0)
+ {
+ return graph_.new_node<T> (file, line, column, a0);
+ }
+
+ template <typename T, typename A0, typename A1>
+ T&
+ new_node (path const& file, size_t line, size_t column,
+ A0 const& a0, A1 const& a1)
+ {
+ return graph_.new_node<T> (file, line, column, a0, a1);
+ }
+
+ template <typename T, typename A0, typename A1, typename A2>
+ T&
+ new_node (path const& file, size_t line, size_t column,
+ A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ return graph_.new_node<T> (file, line, column, a0, a1, a2);
+ }
+
+ template <typename T, typename A0, typename A1, typename A2, typename A3>
+ T&
+ new_node (path const& file, size_t line, size_t column,
+ A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3)
+ {
+ return graph_.new_node<T> (file, line, column, a0, a1, a2, a3);
+ }
+
+ public:
+ type&
+ new_type (path const& file, size_t l, size_t c, string const& name)
+ {
+ type_map::iterator i (types_.find (name));
+
+ return i != types_.end ()
+ ? *i->second
+ : *(types_[name] = &new_node<type> (file, l, c, name));
+ }
+
+ protected:
+ // Special names edge for the global namespace.
+ //
+ class global_names: public names
+ {
+ public:
+ global_names ()
+ : names ("")
+ {
+ scope_ = 0;
+ }
+
+ void
+ set_left_node (cli_unit&)
+ {
+ }
+
+ void
+ set_right_node (nameable& n)
+ {
+ named_ = &n;
+ }
+
+ void
+ clear_left_node (cli_unit&)
+ {
+ }
+
+ void
+ clear_right_node (nameable& n)
+ {
+ assert (named_ == &n);
+ named_ = 0;
+ }
+ };
+
+ public:
+ void
+ add_edge_left (cli_includes& e)
+ {
+ includes_.push_back (&e);
+ }
+
+ void
+ add_edge_left (cxx_includes& e)
+ {
+ includes_.push_back (&e);
+ }
+
+ void
+ add_edge_left (global_names&)
+ {
+ }
+
+ void
+ add_edge_right (cli_includes&)
+ {
+ }
+
+ using namespace_::add_edge_left;
+ using namespace_::add_edge_right;
+
+ private:
+ typedef std::map<string, type*> type_map;
+
+ private:
+ graph<node, edge>& graph_;
+ includes_list includes_;
+ type_map types_;
+ };
+}
+
+#include <cli/semantics/unit.txx>
+
+#endif // CLI_SEMANTICS_UNIT_HXX
diff --git a/cli/cli/semantics/unit.txx b/cli/cli/semantics/unit.txx
new file mode 100644
index 0000000..99d178f
--- /dev/null
+++ b/cli/cli/semantics/unit.txx
@@ -0,0 +1,108 @@
+// file : cli/semantics/unit.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// license : MIT; see accompanying LICENSE file
+
+namespace semantics
+{
+ template <typename T>
+ T* cli_unit::
+ lookup (std::string const& ss, std::string const& name, bool outer)
+ {
+ using std::string;
+
+ // Resolve the starting scope in this unit, if any.
+ //
+ string::size_type b (0), e;
+ scope* s (0);
+
+ do
+ {
+ e = ss.find ("::", b);
+ string n (ss, b, e == string::npos ? e : e - b);
+
+ if (n.empty ())
+ s = this;
+ else
+ {
+ scope::names_iterator_pair ip (s->find (n));
+
+ for (s = 0; ip.first != ip.second; ++ip.first)
+ if ((s = dynamic_cast<scope*> (&ip.first->named ())))
+ break;
+
+ if (s == 0)
+ break; // No such scope in this unit.
+ }
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+ } while (true);
+
+ // If we have the starting scope, then try to resolve the name in it.
+ //
+ if (s != 0)
+ {
+ b = 0;
+
+ do
+ {
+ e = name.find ("::", b);
+ string n (name, b, e == string::npos ? e : e - b);
+
+ scope::names_iterator_pair ip (s->find (n));
+
+ // If this is the last name, then see if we have the desired type.
+ //
+ if (e == string::npos)
+ {
+ for (; ip.first != ip.second; ++ip.first)
+ if (T* r = dynamic_cast<T*> (&ip.first->named ()))
+ return r;
+ }
+ // Otherwise, this should be a scope.
+ //
+ else
+ {
+ for (s = 0; ip.first != ip.second; ++ip.first)
+ if ((s = dynamic_cast<scope*> (&ip.first->named ())))
+ break;
+
+ if (s == 0)
+ break; // No such inner scope.
+ }
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+ } while (true);
+ }
+
+ // If we are here, then that means the lookup didn't find anything in
+ // this unit. The next step is to examine all the included units.
+ //
+ for (includes_iterator i (includes_begin ()); i != includes_end (); ++i)
+ {
+ if (cli_includes* ci = dynamic_cast<cli_includes*> (&*i))
+ if (T* r = ci->includee ().lookup<T> (ss, name, false))
+ return r;
+ }
+
+ // If we still haven't found anything, then the next step is to search
+ // one-outer scope, unless it is the global namespace.
+ //
+ if (outer && !ss.empty ())
+ {
+ string n (ss, 0, ss.rfind ("::"));
+ return lookup<T> (n, name, true);
+ }
+
+ return 0;
+ }
+}