commit 9a944cd50046badb614f1f7a89c60a3648722e15 Author: Jonathan Müller Date: Fri Jan 20 23:00:47 2017 +0100 Add basic entity diff --git a/include/cppast/cpp_entity.hpp b/include/cppast/cpp_entity.hpp new file mode 100644 index 0000000..0276d62 --- /dev/null +++ b/include/cppast/cpp_entity.hpp @@ -0,0 +1,61 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_CPP_ENTITY_HPP_INCLUDED +#define CPPAST_CPP_ENTITY_HPP_INCLUDED + +#include + +#include + +namespace cppast +{ + enum class cpp_entity_type; + + /// The base class for all entities in the C++ AST. + class cpp_entity : detail::intrusive_list_node + { + public: + cpp_entity(const cpp_entity&) = delete; + cpp_entity& operator=(const cpp_entity&) = delete; + + virtual ~cpp_entity() noexcept = default; + + /// \returns The type of the entity. + cpp_entity_type type() const noexcept + { + return do_get_entity_type(); + } + + /// \returns The name of the entity. + /// The name is the string associated with the entity's declaration. + const std::string& name() const noexcept + { + return name_; + } + + /// \returns A [ts::optional_ref]() to the parent entity in the AST. + type_safe::optional_ref parent() const noexcept + { + return parent_; + } + + protected: + /// \effects Creates it giving it the parent entity and the name. + cpp_entity(type_safe::optional_ref parent, std::string name) + : parent_(std::move(parent)), name_(std::move(name)) + { + } + + private: + virtual cpp_entity_type do_get_entity_type() const noexcept = 0; + + type_safe::optional_ref parent_; + std::string name_; + + friend detail::intrusive_list_access; + }; +} // namespace cppast + +#endif // CPPAST_CPP_ENTITY_HPP_INCLUDED diff --git a/include/cppast/cpp_entity_type.hpp b/include/cppast/cpp_entity_type.hpp new file mode 100644 index 0000000..d79627c --- /dev/null +++ b/include/cppast/cpp_entity_type.hpp @@ -0,0 +1,17 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_CPP_ENTITY_TYPE_HPP_INCLUDED +#define CPPAST_CPP_ENTITY_TYPE_HPP_INCLUDED + +namespace cppast +{ + /// All possible types of C++ entities. + enum class cpp_entity_type + { + + }; +} // namespace cppast + +#endif // CPPAST_CPP_ENTITY_TYPE_HPP_INCLUDED diff --git a/include/cppast/detail/assert.hpp b/include/cppast/detail/assert.hpp new file mode 100644 index 0000000..e855936 --- /dev/null +++ b/include/cppast/detail/assert.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_ASSERT_HPP_INCLUDED +#define CPPAST_ASSERT_HPP_INCLUDED + +#include + +namespace cppast +{ + namespace detail + { + struct assert_handler : debug_assert::set_level<1>, debug_assert::default_handler + { + }; + } +} // namespace cppast::detail + +#endif // CPPAST_ASSERT_HPP_INCLUDED diff --git a/include/cppast/detail/intrusive_list.hpp b/include/cppast/detail/intrusive_list.hpp new file mode 100644 index 0000000..4e685f8 --- /dev/null +++ b/include/cppast/detail/intrusive_list.hpp @@ -0,0 +1,189 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_INTRUSIVE_LIST_HPP_INCLUDED +#define CPPAST_INTRUSIVE_LIST_HPP_INCLUDED + +#include +#include + +#include + +#include + +namespace cppast +{ + namespace detail + { + template + class intrusive_list; + + template + class intrusive_list_node + { + std::unique_ptr next_; + + template + friend struct intrusive_list_access; + }; + + template + struct intrusive_list_access + { + template + static T* get_next(const intrusive_list_node& obj) + { + static_assert(std::is_base_of::value, "must be a base"); + return static_cast(obj.next_.get()); + } + + template + static T* set_next(intrusive_list_node& obj, std::unique_ptr node) + { + static_assert(std::is_base_of::value, "must be a base"); + obj.next_ = std::move(node); + return obj.next_.get(); + } + }; + + template + class intrusive_list_iterator + { + public: + using value_type = T; + using reference = T&; + using pointer = T*; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + + intrusive_list_iterator() noexcept : cur_(nullptr) + { + } + + reference operator*() const noexcept + { + return *cur_; + } + + pointer operator->() const noexcept + { + return cur_; + } + + intrusive_list_iterator& operator++() noexcept + { + cur_ = intrusive_list_access::get_next(*cur_); + return *this; + } + + intrusive_list_iterator operator++(int)noexcept + { + auto tmp = *this; + ++(*this); + return tmp; + } + + friend bool operator==(const intrusive_list_iterator& a, + const intrusive_list_iterator& b) noexcept + { + return a.cur_ == b.cur_; + } + + friend bool operator!=(const intrusive_list_iterator& a, + const intrusive_list_iterator& b) noexcept + { + return !(a == b); + } + + private: + intrusive_list_iterator(T* ptr) : cur_(ptr) + { + } + + T* cur_; + + friend intrusive_list; + }; + + template + class intrusive_list + { + public: + intrusive_list() = default; + + //=== modifiers ===// + void push_back(std::unique_ptr obj) noexcept + { + DEBUG_ASSERT(obj, detail::assert_handler{}); + + if (last_) + { + auto ptr = intrusive_list_access::set_next(last_.value(), std::move(obj)); + last_ = type_safe::opt_cref(ptr); + } + else + { + first_ = std::move(obj); + last_ = type_safe::opt_ref(first_.get()); + } + } + + //=== accesors ===// + bool empty() const noexcept + { + return first_ == nullptr; + } + + type_safe::optional_ref front() noexcept + { + return type_safe::opt_ref(first_.get()); + } + + type_safe::optional_ref front() const noexcept + { + return type_safe::opt_cref(first_.get()); + } + + type_safe::optional_ref back() noexcept + { + return last_; + } + + type_safe::optional_ref back() const noexcept + { + return last_; + } + + //=== iterators ===// + using iterator = intrusive_list_iterator; + using const_iterator = intrusive_list_iterator; + + iterator begin() noexcept + { + return iterator(first_.get()); + } + + iterator end() noexcept + { + return {}; + } + + const_iterator begin() const noexcept + { + return const_iterator(first_.get()); + } + + const_iterator end() const noexcept + { + return {}; + } + + private: + std::unique_ptr first_; + type_safe::optional_ref last_; + }; + } +} // namespace cppast::detail + +#endif // CPPAST_INTRUSIVE_LIST_HPP_INCLUDED