eolian_cxx: rework context code, also more flexible scope indentation generator
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>
Fri, 22 Mar 2019 21:34:29 +0000 (18:34 -0300)
committerYeongjong Lee <yj34.lee@samsung.com>
Tue, 2 Apr 2019 03:45:17 +0000 (12:45 +0900)
Summary:
Context management classes now store constant copies of the tags they
are supposed to hold. So, they are immutable objects now.
Functions that manipulate context create new object copies as needed.
`constexpr` was added for class constructor and functions.

Indentation generator now used four space by default.
Also, the amount of desired spaces can now be specified at call site.

Added helper methods to return 'indented' and 'unindented' version of a
given indentation generator object.

Test Plan: ninja test

Reviewers: felipealmeida, lauromoura

Reviewed By: lauromoura

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D8467

src/lib/eolian_cxx/grammar/context.hpp
src/lib/eolian_cxx/grammar/indentation.hpp

index e483920..6fb171a 100644 (file)
@@ -5,33 +5,50 @@ namespace efl { namespace eolian { namespace grammar {
 
 struct context_null {};
 
-template <typename Tag, typename Tail =  context_null>
+template <typename Tag, typename Tail = context_null>
 struct context_cons
 {
-  Tag tag;
-  Tail const& tail;
-};
-      
-template <typename Tag>
-struct context_cons<Tag, context_null>
-{
-  Tag tag;
-  context_null tail;
+  typename std::remove_reference<Tag>::type const tag;
+  typename std::remove_reference<Tail>::type const tail;
 };
 
 template <typename NewTag, typename Tag, typename Tail>
-context_cons<NewTag, context_cons<Tag, Tail>>
-context_add_tag(NewTag tag, context_cons<Tag, Tail> const& context)
+constexpr context_cons<NewTag, context_cons<Tag, Tail>>
+context_add_tag(NewTag const& tag, context_cons<Tag, Tail> const& context)
 {
   return context_cons<NewTag, context_cons<Tag, Tail>>{tag, context};
 }
 template <typename NewTag>
-context_cons<NewTag, context_null>
-context_add_tag(NewTag tag, context_null context)
+constexpr context_cons<NewTag, context_null>
+context_add_tag(NewTag const& tag, context_null context)
 {
   return context_cons<NewTag, context_null>{tag, context};
 }
 
+template <typename Tag, typename SameTag, typename Tail>
+constexpr context_cons<SameTag, Tail>
+context_replace_tag(Tag const& tag, context_cons<SameTag, Tail> const& context
+                    , typename std::enable_if<std::is_same<Tag, SameTag>::value>::type* = nullptr)
+{
+  return {tag, context.tail};
+}
+
+template <typename Tag, typename OtherTag, typename Tail>
+constexpr context_cons<OtherTag, Tail>
+context_replace_tag(Tag const& tag, context_cons<OtherTag, Tail> const& context
+                    , typename std::enable_if<!std::is_same<Tag, OtherTag>::value>::type* = nullptr)
+{
+  return {context.tag, context_replace_tag(tag, context.tail)};
+}
+
+template <typename Tag>
+constexpr context_null
+context_replace_tag(Tag const& tag, context_null const&)
+{
+  static_assert(std::is_same<Tag, context_null>::value, "Tag type not available in this generation context");
+  return tag;
+}
+
 template <typename Tag, typename Context>
 struct tag_check;
 template <typename Tag, typename Tail>
@@ -42,25 +59,26 @@ template <typename Tag, typename OtherTag, typename Context>
 struct tag_check<Tag, context_cons<OtherTag, Context>> : tag_check<Tag, Context> {};
 
 template <typename Tag, typename SameTag, typename Tail> 
-Tag const& context_find_tag(context_cons<SameTag, Tail> const& context
+constexpr Tag const& context_find_tag(context_cons<SameTag, Tail> const& context
                             , typename std::enable_if<std::is_same<Tag, SameTag>::value>::type* = nullptr)
 {
   return context.tag;
 }
 
 template <typename Tag, typename OtherTag, typename Tail> 
-Tag const& context_find_tag(context_cons<OtherTag, Tail> const& context
+constexpr Tag const& context_find_tag(context_cons<OtherTag, Tail> const& context
                             , typename std::enable_if<!std::is_same<Tag, OtherTag>::value>::type* = nullptr)
 {
   return context_find_tag<Tag>(context.tail);
 }
 
-template <typename Tag, typename OtherTag, typename Tail> 
-Tag const& context_find_tag(context_null const&)
+template <typename Tag>
+constexpr Tag const& context_find_tag(context_null const& context)
 {
-  throw std::logic_error("Context for generation not available");
+  static_assert(std::is_same<Tag, context_null>::value, "Tag type not available in this generation context");
+  return context;
 }
-      
+
 } } }
 
 #endif
index 897be03..347974f 100644 (file)
@@ -8,22 +8,36 @@ namespace efl { namespace eolian { namespace grammar {
 
 struct scope_tab_generator
 {
-  scope_tab_generator(int n)
-    : n(n) {}
-  
+  constexpr scope_tab_generator(int n, int m = 4)
+    : n(n)
+    , m(m)
+  {}
+  constexpr scope_tab_generator(scope_tab_generator const&) = default;
+  scope_tab_generator& operator=(scope_tab_generator const&) = default;
+
   template <typename OutputIterator, typename Context>
   bool generate(OutputIterator sink, attributes::unused_type, Context const&) const
   {
      for(int i = 0; i != n; ++i)
        {
-          *sink++ = ' ';
-          *sink++ = ' ';
-          *sink++ = ' ';
+          for(int j = 0; j != m; ++j)
+            *sink++ = ' ';
        }
      return true;
   }
 
+  constexpr scope_tab_generator inc(int nplus = 1) const
+  {
+     return {n+nplus, m};
+  }
+
+  constexpr scope_tab_generator dec(int nminus = 1) const
+  {
+     return {n-nminus, m};
+  }
+
   int n;
+  int m;
 };
 
 template <>
@@ -33,9 +47,14 @@ struct is_generator<scope_tab_generator> : std::true_type {};
       
 struct scope_tab_terminal
 {
-  scope_tab_generator operator()(int n) const
+  scope_tab_generator operator()(int n, int m = 4) const
+  {
+     return {n, m};
+  }
+
+  operator scope_tab_generator() const
   {
-     return scope_tab_generator(n);
+     return {1};
   }
 } const scope_tab = {};