diff --git a/src/app/main.cpp b/src/app/main.cpp index 63620f6..5fec763 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -10,6 +10,216 @@ #include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +template < typename Iter > +void join(Iter begin, Iter end, std::string const & separator, std::string & result) { + if(begin != end) + result += std::string{"'"} + *begin++ + "'"; + while(begin != end) + result += separator + "'" + *begin++ + "'"; +} + +void explode() { + std::string name{"Reflect"}; + std::string out; + out.reserve(10 + name.size() * 4); + out += "Name<"; + join(name.begin(), name.end(), ",", out); + out += ">"; + puts(out.c_str()); +} + +struct Reflect { + Reflect() {} + Reflect(int) {} + + virtual ~Reflect() = default; + + virtual void foo() { + puts("FOO\n"); + } + + void foo() const { + puts("const FOO\n"); + } + + void bar() { + puts("BAR\n"); + } + + void bar() const { + puts("const BAR\n"); + } + + int doSomething() { + return 5; + } +}; + +struct AndThis { + void baz() { + puts("BAZ\n"); + } +}; + +namespace meta { +template < typename Class > +struct reflection : public std::false_type {}; + +namespace api { + enum class entity_type { // + CppClass, + CppClassCtor, + CppClassMethod + }; + + template < typename Meta > + constexpr auto name(const Meta & m) { + using namespace boost::hana::literals; + return m.name(); + } + + template < typename Meta > + constexpr auto fn(const Meta & m) { + return m._fn; + } + + template + constexpr auto is_virtual(const Meta &m){ + return m.is_virtual(); + } + + template < typename Entities, typename Visitor > + void visit(Entities && entities, Visitor && visitor) { + boost::hana::for_each(entities, visitor); + } + + template < typename Meta > + struct ctor_t { + using type = typename Meta::signature; + }; + +} // namespace api + +namespace { + template < char... s > + constexpr char const string_storage[sizeof...(s) + 1] = {s..., '\0'}; +} + +namespace details { + template < api::entity_type type_ > + struct CppEntity { + static constexpr api::entity_type value{type_}; + static constexpr auto type() { + return value; + } + }; +} // namespace details + +template < char... name_ > +struct Name { + static constexpr const char * name() { + return &string_storage< name_... >[0]; + } +}; + +template < typename Name, typename Signature, bool Virtual > +struct MetaMethod : public Name, public details::CppEntity< api::entity_type::CppClassMethod > { + using signature = Signature; + + signature _fn; + static constexpr bool is_virtual() { + return Virtual; + }; + + constexpr MetaMethod(Signature fn) : _fn{fn} {} +}; + +template < typename Name, typename Signature > +struct MetaCtor : public Name, public details::CppEntity< api::entity_type::CppClassCtor > { + using signature = Signature; +}; + +template < typename Name > +struct MetaClass : public Name, public details::CppEntity< api::entity_type::CppClass > {}; + +template <> +struct reflection< Reflect > : public std::true_type { + static constexpr auto methods() { + return std::make_tuple( // + MetaMethod< Name< 'f', 'o', 'o' >, void (Reflect::*)(), true >(&Reflect::foo), // + MetaMethod< Name< 'f', 'o', 'o' >, void (Reflect::*)() const, false >(&Reflect::foo), // + MetaMethod< Name< 'b', 'a', 'r' >, void (Reflect::*)(), false >(&Reflect::bar), // + MetaMethod< Name< 'b', 'a', 'r' >, void (Reflect::*)() const, false >(&Reflect::bar) // + ); + } + static constexpr auto ctors() { + return std::make_tuple( // + MetaCtor< Name< 'R', 'e', 'f', 'l', 'e', 'c', 't' >, Reflect() >(), // + MetaCtor< Name< 'R', 'e', 'f', 'l', 'e', 'c', 't' >, Reflect(int) >() // + ); + } + + static constexpr auto class_info() { + return std::make_tuple(MetaClass< Name< 'R', 'e', 'f', 'l', 'e', 'c', 't' > >()); + } + + static constexpr auto all() { + return std::tuple_cat(class_info(), ctors(), methods()); + } +}; + +} // namespace meta + +enum class TestEnum{one,two}; + +int bootstrap() { + chaiscript::ChaiScript chai; + meta::api::visit(meta::reflection< Reflect >::all(), [&chai](const auto entity) { + if constexpr(entity.type() == meta::api::entity_type::CppClassMethod) { + puts("got method"); + if constexpr (meta::api::is_virtual(entity)){ + puts(" virtual"); + } + chai.add(chaiscript::fun(meta::api::fn(entity)), meta::api::name(entity)); + } else if constexpr(entity.type() == meta::api::entity_type::CppClassCtor) { + puts("got ctor"); + chai.add(chaiscript::constructor< typename meta::api::ctor_t< decltype(entity) >::type >(), meta::api::name(entity)); + } else if constexpr(entity.type() == meta::api::entity_type::CppClass) { + puts("got class"); + chai.add(chaiscript::user_type< Reflect >(), meta::api::name(entity)); + } + }); + + using namespace std::string_literals; + chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module()); + chaiscript::utility::add_class< TestEnum >( + *m, "EnumTest"s, std::vector{std::pair{TestEnum::one, "one"s}, std::pair{TestEnum::two, "two"s}}); + + chai.eval(R"( + var test = Reflect() + test.foo() + test.bar() + )"); + + explode(); + + return 0; + // return example_main(argc, argv, {}, &print_ast); +} + static auto _createSinks() { std::vector< spdlog::sink_ptr > sinks; auto stdout_sink = spdlog::sinks::stdout_sink_mt::instance(); @@ -41,8 +251,8 @@ static auto createDbConnection(std::function< bool(const std::string &, std::str } } -std::unique_ptr< Wt::WApplication >createApplication (const Wt::WEnvironment &env) { - auto server = env.server(); +std::unique_ptr< Wt::WApplication > createApplication(const Wt::WEnvironment & env) { + auto server = env.server(); auto connection = createDbConnection([server](const auto & name, auto & val) { // return server->readConfigurationProperty(name, val); }); @@ -53,9 +263,10 @@ std::unique_ptr< Wt::WApplication >createApplication (const Wt::WEnvironment &en } int main(int argc, char ** argv) { - initializeLogs(); - eedb::WebServer server{argc, argv}; + bootstrap(); +// initializeLogs(); +// eedb::WebServer server{argc, argv}; - server.run(createApplication); +// server.run(createApplication); return 0; }