#include #include #include #include #include #include #include #include #include namespace saw { namespace schema { using CVar = Struct< Member, Member, Member >; using CStruct = Struct< Member, Member, Member, "members"> >; using CFunction = Struct< Member, Member, Member, "params">, Member >; using CIface = Struct< Member, Member,"structs">, Member,"functions"> >; } /** * Type meant to provide future help if I decide to introduce more maps */ /** namespace schema { using namespace saw::schema; Pseudo flattened using Foo = Struct< Member, "a"> Member, "b"> >; Needs to be flattened to template using FlattenedSchemaElement = Struct< Member, "path">, Member >; // Illegal, but doable with more lines of code // Just use typename... T and // "T..." for // "Member,Names>...>" // and specialize somewhere else template using FlattenedSchema = Struct< Member, Member, Names>... >; } */ template struct schema_flattener { static_assert(always_false, "Not supported"); }; template struct schema_flattener,schema::Member...>, Res> { }; /** * Helper to determine if we are dealing with primitive types */ template struct c_is_primitive { static constexpr bool value = false; }; template struct c_is_primitive> { static constexpr bool value = true; }; template struct c_primitive_string { static_assert(always_false, "Not supported"); }; template<> struct c_primitive_string { static constexpr std::string_view value = "int8_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "int16_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "int32_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "int64_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "uint8_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "uint16_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "uint32_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "uint64_t"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "float"; }; template<> struct c_primitive_string { static constexpr std::string_view value = "double"; }; bool c_interface_function_exists(data& state, const std::string_view& name){ auto& funcs = state.template get<"functions">(); for(uint64_t i = 0; i < funcs.size(); ++i){ if(funcs.at(i).get<"name">() == name){ return true; } } return false; } template struct c_data_translater { static_assert(always_false, "Not supported"); }; template struct c_data_translater> { using Schema = schema::Primitive; static error_or generate(data& state, data& prim){ /// @TODO Check if exists in CVars already try{ std::stringstream iss; schema_stringify::apply(iss); prim.template get<"schema">().set(iss.str()); }catch(const std::exception&){ return make_error(); } return void_t{}; } }; template struct c_data_translater> { using Schema = schema::Function; static error_or generate(data& state, const std::string_view& func_name){ if(c_interface_function_exists(state, func_name)){ return make_error("Function already exists"); } auto& funcs = state.template get<"functions">(); data function; function.template get<"name">().set(std::string{func_name}); try{ std::stringstream iss; schema_stringify::apply(iss); function.template get<"schema">().set(iss.str()); }catch(const std::exception&){ return make_error(); } { auto& c_var = function.template get<"return">(); c_var.template get<"name">().set("ret_val"); auto eov = c_data_translater::generate(state, c_var); if(eov.is_error()){ return eov; } } { auto eov = funcs.add(std::move(function)); if(eov.is_error()){ return eov; } } return void_t{}; } }; template struct c_data_translater...>> { using Schema = schema::Interface...>; template static error_or generate_ele(data& state){ using InnerSchema = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { auto eov = c_data_translater::generate(state, Literal.view()); if(eov.is_error()){ return eov; } } /** * Continue if elements remain or finish */ if constexpr ( (i+1) < sizeof...(Funcs) ){ return generate_ele(state); } return void_t{}; } static error_or generate(data& state){ try{ std::stringstream iss; schema_stringify::apply(iss); state.template get<"schema">().set(iss.str()); }catch(const std::exception&){ return make_error(); } if constexpr (sizeof...(Funcs) > 0){ return generate_ele<0>(state); } return void_t{}; } }; template error_or generate_c_interface(data& state){ auto eov = c_data_translater::generate(state); return eov; } }