From 720c5a33b6a49cf328fdd7611f49153cf8f60247 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 8 Apr 2020 14:51:57 +0300 Subject: Separate tests and examples into individual packages Also make cli module to be explicitly enabled via the config.cli configuration variable. --- cli/cli/semantics/class.cxx | 39 ++++ cli/cli/semantics/class.hxx | 106 ++++++++++ cli/cli/semantics/doc.cxx | 27 +++ cli/cli/semantics/doc.hxx | 22 +++ cli/cli/semantics/elements.cxx | 129 +++++++++++++ cli/cli/semantics/elements.hxx | 407 +++++++++++++++++++++++++++++++++++++++ cli/cli/semantics/expression.cxx | 27 +++ cli/cli/semantics/expression.hxx | 76 ++++++++ cli/cli/semantics/namespace.cxx | 27 +++ cli/cli/semantics/namespace.hxx | 26 +++ cli/cli/semantics/option.cxx | 47 +++++ cli/cli/semantics/option.hxx | 189 ++++++++++++++++++ cli/cli/semantics/unit.cxx | 63 ++++++ cli/cli/semantics/unit.hxx | 310 +++++++++++++++++++++++++++++ cli/cli/semantics/unit.txx | 108 +++++++++++ 15 files changed, 1603 insertions(+) create mode 100644 cli/cli/semantics/class.cxx create mode 100644 cli/cli/semantics/class.hxx create mode 100644 cli/cli/semantics/doc.cxx create mode 100644 cli/cli/semantics/doc.hxx create mode 100644 cli/cli/semantics/elements.cxx create mode 100644 cli/cli/semantics/elements.hxx create mode 100644 cli/cli/semantics/expression.cxx create mode 100644 cli/cli/semantics/expression.hxx create mode 100644 cli/cli/semantics/namespace.cxx create mode 100644 cli/cli/semantics/namespace.hxx create mode 100644 cli/cli/semantics/option.cxx create mode 100644 cli/cli/semantics/option.hxx create mode 100644 cli/cli/semantics/unit.cxx create mode 100644 cli/cli/semantics/unit.hxx create mode 100644 cli/cli/semantics/unit.txx (limited to 'cli/cli/semantics') 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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_CLASS_HXX +#define CLI_SEMANTICS_CLASS_HXX + +#include + +#include + +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_list; + + public: + bool + abstract () const + { + return abstract_; + } + + void + abstract (bool a) + { + abstract_ = a; + } + + public: + typedef pointer_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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_DOC_HXX +#define CLI_SEMANTICS_DOC_HXX + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_ELEMENTS_HXX +#define CLI_SEMANTICS_ELEMENTS_HXX + +#include +#include +#include +#include +#include // std::size_t +#include // std::abort +#include // std::pair +#include + +#include + +#include +#include + +#include + +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 doc_strings; + + // + // + class node; + class edge; + + + // + // + class edge + { + public: + virtual + ~edge () {} + + public: + typedef semantics::context context_type; + + context_type& + context () + { + return context_; + } + + public: + template + bool + is_a () const + { + return dynamic_cast (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 + bool + is_a () const + { + return dynamic_cast (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 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_list; + typedef std::map list_iterator_map; + typedef std::map names_map; + + public: + typedef pointer_iterator names_iterator; + typedef pointer_iterator names_const_iterator; + + typedef + std::pair + 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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_EXPRESSION_HXX +#define CLI_SEMANTICS_EXPRESSION_HXX + +#include +#include + +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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_NAMESPACE_HXX +#define CLI_SEMANTICS_NAMESPACE_HXX + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_OPTION_HXX +#define CLI_SEMANTICS_OPTION_HXX + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#include + +#include + +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 +// license : MIT; see accompanying LICENSE file + +#ifndef CLI_SEMANTICS_UNIT_HXX +#define CLI_SEMANTICS_UNIT_HXX + +#include +#include +#include + +#include +#include + +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, public namespace_ + { + typedef std::vector 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 + T* + lookup (std::string const& scope, + std::string const& name, + bool outer = true); + + public: + typedef + pointer_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 (*this, *this); + } + + public: + template + T& + new_node (path const& file, size_t line, size_t column) + { + return graph_.new_node (file, line, column); + } + + template + T& + new_node (path const& file, size_t line, size_t column, A0 const& a0) + { + return graph_.new_node (file, line, column, a0); + } + + template + T& + new_node (path const& file, size_t line, size_t column, + A0 const& a0, A1 const& a1) + { + return graph_.new_node (file, line, column, a0, a1); + } + + template + 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 (file, line, column, a0, a1, a2); + } + + template + 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 (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 (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 type_map; + + private: + graph& graph_; + includes_list includes_; + type_map types_; + }; +} + +#include + +#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 +// license : MIT; see accompanying LICENSE file + +namespace semantics +{ + template + 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 (&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 (&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 (&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 (&*i)) + if (T* r = ci->includee ().lookup (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 (n, name, true); + } + + return 0; + } +} -- cgit v1.1