Skip to content

Commit

Permalink
Nicer find-replace for enum & function serializers.
Browse files Browse the repository at this point in the history
  • Loading branch information
chakaz committed Dec 14, 2016
1 parent 6b09251 commit 93564aa
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 67 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_executable(
gen/serializer.cpp gen/serializer.hpp
gen/serializer.enum.cpp gen/serializer.enum.hpp
gen/serializer.function.cpp gen/serializer.function.hpp
gen/serializer.util.cpp gen/serializer.util.hpp
gen/types.cpp gen/types.hpp)
target_link_libraries(reflang ${CLANG_LIBS})

Expand Down
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ This file is intended for Reflang author.
## General
* Support header-only or header+cpp
* Library for base types, registry, etc
* Nicer serializers - some kind of framework - replace with regex?
* Consistent style for names of functions, methods, variables, members, ...

## Functions
Expand Down
95 changes: 50 additions & 45 deletions gen/serializer.enum.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "serializer.enum.hpp"

#include <memory>
#include <sstream>
#include <unordered_set>
#include <vector>

#include "serializer.util.hpp"

using namespace std;
using namespace reflang;

Expand Down Expand Up @@ -46,10 +49,11 @@ void serializer::SerializeEnum(ostream& o, const Enum& the_enum)
vector<string> values = GetEnumValues(the_enum);

const string& name = the_enum.GetFullName();
o << R"(template <>
struct Enum<)" << name << R"(>
stringstream tmpl;
tmpl << R"(template <>
struct Enum<%name%>
{
using EnumType = )" << name << R"(;
using EnumType = %name%;
struct ConstIterator
{
Expand All @@ -60,28 +64,28 @@ struct Enum<)" << name << R"(>
)";
if (unique_values.empty())
{
o << " assert(false);\n";
tmpl << " assert(false);\n";
}
else
{
o << R"( switch (value_)
tmpl << R"( switch (value_)
{
)";
for (int i = 1; i < unique_values.size(); ++i)
{
const auto& prev = unique_values[i - 1];
const auto& it = unique_values[i];
o << " case EnumType::" << prev << ":\n";
o << " value_ = EnumType::" << it << ";\n";
o << " break;\n";
tmpl << " case EnumType::" << prev << ":\n";
tmpl << " value_ = EnumType::" << it << ";\n";
tmpl << " break;\n";
}
o << " case EnumType::" << unique_values.back() << ":\n";
o << R"( last_ = true;
tmpl << " case EnumType::" << unique_values.back() << ":\n";
tmpl << R"( last_ = true;
break;
}
)";
}
o << R"( return *this;
tmpl << R"( return *this;
}
ConstIterator operator++(int)
Expand All @@ -96,36 +100,36 @@ struct Enum<)" << name << R"(>
)";
if (unique_values.empty())
{
o << " assert(false);\n";
tmpl << " assert(false);\n";
}
else
{
o << R"( if (last_)
tmpl << R"( if (last_)
{
last_ = false;
)";
o << "value_ = EnumType::" << unique_values.back() << ";\n";
o << R"( }
tmpl << "value_ = EnumType::" << unique_values.back() << ";\n";
tmpl << R"( }
else
{
switch (value_)
{
)";
o << " case EnumType::" << unique_values.front() << ":\n";
o << " assert(false);\n";
o << " break;\n";
tmpl << " case EnumType::" << unique_values.front() << ":\n";
tmpl << " assert(false);\n";
tmpl << " break;\n";
for (int i = 1; i < unique_values.size(); ++i)
{
const auto& prev = unique_values[i - 1];
const auto& it = unique_values[i];
o << " case EnumType::" << it << ":\n";
o << " value_ = EnumType::" << prev << ";\n";
o << " break;\n";
tmpl << " case EnumType::" << it << ":\n";
tmpl << " value_ = EnumType::" << prev << ";\n";
tmpl << " break;\n";
}
o << " }\n";
o << " }\n";
tmpl << " }\n";
tmpl << " }\n";
}
o << R"( return *this;
tmpl << R"( return *this;
}
ConstIterator operator--(int)
Expand Down Expand Up @@ -156,17 +160,17 @@ struct Enum<)" << name << R"(>
)";
if (unique_values.empty())
{
o << " return end();\n";
tmpl << " return end();\n";
}
else
{
o << R"( ConstIterator it;
tmpl << R"( ConstIterator it;
it.last_ = false;
it.value_ = EnumType::)" << unique_values.front() << R"(;
return it;
)";
}
o << R"( }
tmpl << R"( }
ConstIterator end() const
{
Expand All @@ -184,51 +188,52 @@ struct Enum<)" << name << R"(>
)";
if (values.empty())
{
o << " return false;\n";
tmpl << " return false;\n";
}
else
{
for (size_t i = 0; i < values.size(); ++i)
{
o << " ";
tmpl << " ";
if (i != 0)
{
o << "else ";
tmpl << "else ";
}
o << "if (s == \"" << values[i] << "\")\n";
o << " {\n";
o << " value = EnumType::" << values[i] <<";\n";
o << " return true;\n";
o << " }\n";
tmpl << "if (s == \"" << values[i] << "\")\n";
tmpl << " {\n";
tmpl << " value = EnumType::" << values[i] <<";\n";
tmpl << " return true;\n";
tmpl << " }\n";
}
o << R"( else
tmpl << R"( else
{
return false;
}
)";
}
o << R"( }
tmpl << R"( }
static std::string Translate(EnumType e)
{
)";
if (unique_values.empty())
{
o << " return std::string();\n";
tmpl << " return std::string();\n";
}
else
{
o << " switch (e)\n";
o << " {\n";
tmpl << " switch (e)\n";
tmpl << " {\n";
for (const auto& value : unique_values)
{
o << " case EnumType::" << value << ":\n";
o << " return \"" << value <<"\";\n";
o << " break;\n";
tmpl << " case EnumType::" << value << ":\n";
tmpl << " return \"" << value <<"\";\n";
tmpl << " break;\n";
}
o << " }\n";
tmpl << " }\n";
}
o << R"( }
tmpl << R"( }
};
)";
o << ReplaceAll(tmpl.str(), { {"%name%", the_enum.GetFullName()} });
}
56 changes: 35 additions & 21 deletions gen/serializer.function.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
#include "serializer.function.hpp"

#include <sstream>

#include "serializer.util.hpp"

using namespace std;
using namespace reflang;

void serializer::SerializeFunction(ostream& o, const Function& f)
{
string name_without_colons = f.GetFullName();
std::replace(
name_without_colons.begin(), name_without_colons.end(), ':', '_');

o << R"(template <>
class Function<decltype()" << f.GetFullName() << "), " << f.GetFullName()
<< R"(> : public IFunction
stringstream tmpl;
tmpl << R"(template <>
class Function<decltype(%name%), %name%> : public IFunction
{
int num_args() const override
{
return )" << f.Arguments.size() << R"(;
return %arg_count%;
}
const std::string& GetName() override
{
static std::string name = ")" << f.GetFullName() << R"(";
static std::string name = "%name%";
return name;
}
Expand All @@ -28,34 +29,47 @@ class Function<decltype()" << f.GetFullName() << "), " << f.GetFullName()
if (args.size() != this->num_args())
{
throw std::invalid_argument("count");
}
)";
})";
if (f.ReturnType == "void")
{
o << " " << f.GetFullName() << "();\n";
o << " return Object();\n";
tmpl << R"(
%name%();
return Object();)";
}
else
{
o << " return Object(" << f.GetFullName() << "());\n";
tmpl << R"(
return Object(%name%());)";
}
tmpl << R"(
}
o << R"( }
};
namespace
{
// Object to auto-register )" << f.GetFullName() << R"(.
struct )" << name_without_colons << R"(_registrar
// Object to auto-register %name%.
struct %name_without_colons%_registrar
{
)" << name_without_colons << R"(_registrar()
%name_without_colons%_registrar()
{
::reflang::registry::internal::Register(
std::make_unique<
Function<
decltype()" << f.GetFullName() << R"(),
)" << f.GetFullName() << R"(>>());
decltype(%name%),
%name%>>());
}
} )" << name_without_colons << R"(_instance;
} %name_without_colons%_instance;
}
)";
string name_without_colons = f.GetFullName();
std::replace(
name_without_colons.begin(), name_without_colons.end(), ':', '_');

o << ReplaceAll(
tmpl.str(),
{
{"%name%", f.GetFullName()},
{"%arg_count%", to_string(f.Arguments.size())},
{"%name_without_colons%", name_without_colons}
});
}
19 changes: 19 additions & 0 deletions gen/serializer.util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "serializer.util.hpp"

#include <regex>

using namespace reflang;
using namespace std;

string serializer::ReplaceAll(
const string& text,
initializer_list<FromToPair> pairs)
{
string result = text;
for (const auto& pair : pairs)
{
regex replace(pair.first);
result = regex_replace(result, replace, pair.second);
}
return result;
}
21 changes: 21 additions & 0 deletions gen/serializer.util.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef REFLANG_SERIALIZER_UTIL_HPP
#define REFLANG_SERIALIZER_UTIL_HPP

#include <string>
#include <utility>

namespace reflang
{
namespace serializer
{
using FromToPair = std::pair<std::string, std::string>;

std::string ReplaceAll(
const std::string& text,
std::initializer_list<FromToPair> from_to_pairs);
}
}

#endif //REFLANG_SERIALIZER_UTIL_HPP


0 comments on commit 93564aa

Please sign in to comment.