From f8c6ec7a18b33deba530b15a5779556233e8057b Mon Sep 17 00:00:00 2001 From: "Claudius \"keldu\" Holeksa" Date: Fri, 8 Mar 2024 21:54:31 +0100 Subject: codec,tools: Working on better c iface generation --- modules/tools/c++/c_gen_iface.hpp | 474 ++++++++++++-------------------------- 1 file changed, 144 insertions(+), 330 deletions(-) (limited to 'modules/tools/c++') diff --git a/modules/tools/c++/c_gen_iface.hpp b/modules/tools/c++/c_gen_iface.hpp index b55816c..2dfa36f 100644 --- a/modules/tools/c++/c_gen_iface.hpp +++ b/modules/tools/c++/c_gen_iface.hpp @@ -12,81 +12,9 @@ #include namespace saw { - -namespace schema { - -using CVar = Struct< - Member, - Member, - Member, - Member, - Member, - Member ->; - -using CStruct = Struct< - Member, - Member, - Member, - Member, "members"> ->; - -using CFunction = Struct< - Member, - Member, - Member, - Member, "params">, - Member ->; - -using CIface = Struct< - Member, - 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>... ->; +namespace binding { +struct C {}; } -*/ - -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 @@ -166,336 +94,222 @@ struct c_primitive_string { static constexpr string_literal value = "double"; }; -error_or> c_interface_find_struct_by_crc32(const data& state, const data& id){ - const auto& strs = state.template get<"structs">(); - for(uint64_t i = 0; i < strs.size(); ++i){ - const auto& str = strs.at(i); - if(str.template get<"crc32">() == id){ - return data{i}; - } - } - return make_error(); -} - -error_or c_interface_add_struct(data& state, data&& val){ - auto& strs = state.template get<"structs">(); - auto eov = strs.add(std::move(val)); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - return void_t{}; -} - -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; -} +struct language_binding_config { + std::string prefix; +}; -template -struct c_data_translater { +namespace impl { +template +struct lang_bind { static_assert(always_false, "Not supported"); }; -template -struct c_data_translater> { - using Schema = schema::Primitive; - static constexpr string_literal c_type_name = c_primitive_string::name; - static constexpr string_literal c_type = c_primitive_string::value; - - static error_or generate(data& state, data& prim){ - try{ - std::stringstream iss; - schema_stringify::apply(iss); - prim.template get<"schema">().set(iss.str()); - prim.template get<"crc32">().set(schema_hash::apply()); - prim.template get<"is_primitive">().set(1); - prim.template get<"type">().set(std::string{c_primitive_string::value.view()}); - }catch(const std::exception&){ - return make_error(); +struct language_binding_state { + struct info { + std::string type; + }; + std::map hashes; +}; + +struct lang_bind_helper { + static error_or append_string(buffer& buff, const std::string_view& str){ + for(uint64_t i = 0; i < str.size(); ++i){ + auto err = buff.push(static_cast(str[i])); + if(!err.template is_type()){ + return err; + } } + return void_t{}; + } + static error_or append_hashed_type(buffer& buff, const std::string_view& prefix, uint32_t hash){ + { + auto eov = append_string(buff, prefix); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, "_"); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, std::to_string(hash)); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = append_string(buff, "_t"); + if(eov.is_error()){ + return eov; + } + } return void_t{}; } }; -template -struct c_data_translater> { - static_assert(N==1, "Doesn't support more than one dimension currently"); - - using Schema = schema::Array; - static constexpr string_literal c_type_name = "array_"_sl + c_data_translater::c_type_name + "_1d"_sl; - static constexpr string_literal c_type = c_type_name + "_t"_sl; - - static error_or generate(data& state, data& arr){ - try{ - { - std::stringstream iss; - schema_stringify::apply(iss); - arr.template get<"schema">().set(iss.str()); - arr.template get<"crc32">().set(schema_hash::apply()); - arr.template get<"is_primitive">().set(0); - } +template +struct lang_bind, binding::C> { + using Schema = schema::Primitive; - /// @todo change this !!!!! - { - auto eov = c_interface_find_struct_by_crc32(state, arr.template get<"crc32">()); - if(eov.is_error()){ - if(false){ - return std::move(eov.get_error()); + static error_or generate(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + constexpr uint64_t hash = schema_hash::apply(); + + { + std::string hash_type_str = cfg.prefix + "_" + std::to_string(hash) + "_t"; + auto emp = state.hashes.emplace(std::make_pair(hash, hash_type_str)); + if(emp.second){ + { + auto eov = lang_bind_helper::append_string(buff, "typedef "); + if(eov.is_error()){ + return eov; } - data str; - str.template get<"schema">() = arr.template get<"schema">(); - str.template get<"crc32">() = arr.template get<"crc32">(); - str.template get<"type">().set(std::string{c_type.view()}); - auto& membs = str.template get<"members">(); - { - data c_var; - std::stringstream iss; - schema_stringify::apply(iss); - c_var.template get<"schema">().set(iss.str()); - c_var.template get<"crc32">().set(schema_hash::apply()); - if constexpr (is_primitive::value){ - c_var.template get<"type">().set(std::string{c_primitive_string::value.view()} + "*"); - c_var.template get<"name">().set(std::string{"data"}); - c_var.template get<"is_primitive">().set(1); - }else{ - return make_error(); - } - - auto eov_add = membs.add(std::move(c_var)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, c_primitive_string::value.view()); + if(eov.is_error()){ + return eov; } - { - data c_var; - std::stringstream iss; - schema_stringify::apply(iss); - c_var.template get<"schema">().set(iss.str()); - c_var.template get<"crc32">().set(schema_hash::apply()); - if constexpr (is_primitive::value){ - c_var.template get<"type">().set(std::string{c_primitive_string::value.view()}); - c_var.template get<"name">().set(std::string{"size"}); - c_var.template get<"is_primitive">().set(1); - }else{ - return make_error(); - } - - auto eov_add = membs.add(std::move(c_var)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, " "); + if(eov.is_error()){ + return eov; } - - /** - * Add the struct to the struct array - */ - { - auto eov_add = c_interface_add_struct(state, std::move(str)); - if(eov_add.is_error()){ - return std::move(eov_add.get_error()); - } + } + { + auto eov = lang_bind_helper::append_string(buff, hash_type_str); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = lang_bind_helper::append_string(buff, ";\n"); + if(eov.is_error()){ + return eov; } } } - arr.template get<"type">().set(std::string{c_type.view()}); - }catch(const std::exception&){ - return make_error(); } return void_t{}; } }; -/* -template -struct c_data_translater> { - using Schema = schema::Struct; - - static error_or generate(data& state){ - return void_t{}; - } -}; -*/ - -template -struct c_parameter_translater { - static_assert(always_false, "Type not supported"); -}; - -template -struct c_parameter_translater...>> { - template - static error_or generate_ele(data& state, data>& params){ - using Type = typename parameter_pack_type::type; - constexpr string_literal Literal = parameter_key_pack_type::literal; +template +struct lang_bind, binding::C> { + static error_or generate(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + constexpr uint64_t input_hash = schema_hash::apply(); + constexpr uint64_t output_hash = schema_hash::apply(); { - auto c_var = data{}; - c_var.template get<"name">().set(std::string{Literal.view()}); - { - auto eov = c_data_translater::generate(state,c_var); + auto eov = lang_bind::generate(buff, cfg, state); if(eov.is_error()){ return eov; } - } - { - auto eov = params.add(std::move(c_var)); + } + { + auto eov = lang_bind::generate(buff, cfg, state); if(eov.is_error()){ return eov; } - } } - if constexpr ( (i+1) < sizeof...(V) ) { - return generate_ele(state, params); - } - return void_t{}; - } - - static error_or generate(data& state, data>& params){ - if constexpr ( sizeof...(V) > 0){ - return generate_ele<0>(state, params); - } return void_t{}; } }; -template -struct c_data_translater> { - using Schema = schema::Function; - - static error_or generate_struct_params(data& state, data>& params){ - return c_parameter_translater::generate(state, params); - } +template +struct lang_bind, binding::C> { + template + static error_or generate_element(buffer& buff, const language_binding_config& cfg, language_binding_state& state){ + using Member = typename parameter_pack_type::type; + using MValue = typename Member::ValueType; + static constexpr string_literal MKey = Member::KeyLiteral; - 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 eov = lang_bind::generate(buff, cfg, state); + if(eov.is_error()){ + return eov; + } } - 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()); - function.template get<"crc32">().set(schema_hash::apply()); - }catch(const std::exception&){ - return make_error(); + { + auto eov = lang_bind_helper::append_string(buff, cfg.prefix); + if(eov.is_error()){ + return eov; + } } - - // Return value { - auto& c_var = function.template get<"return">(); - c_var.template get<"name">().set("ret_val"); - auto eov = c_data_translater::generate(state, c_var); + auto eov = lang_bind_helper::append_string(buff, "_"); if(eov.is_error()){ return eov; } } - - // Request values - auto& params = function.template get<"params">(); - if constexpr (is_primitive::value){ - auto c_var = data{}; - c_var.template get<"name">().set("req_val"); - { - auto eov = c_data_translater::generate(state, c_var); - if(eov.is_error()){ - return eov; - } + { + auto eov = lang_bind_helper::append_string(buff, MKey.view()); + if(eov.is_error()){ + return eov; } - { - auto eov = params.add(std::move(c_var)); - if(eov.is_error()){ - return eov; - } + } + { + auto eov = lang_bind_helper::append_string(buff, "("); + if(eov.is_error()){ + return eov; } - } else { - auto eov = generate_struct_params(state, params); + } + { + auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash::apply()); if(eov.is_error()){ return eov; } } - { - auto eov = funcs.add(std::move(function)); + auto eov = lang_bind_helper::append_string(buff, ","); 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()); + auto eov = lang_bind_helper::append_string(buff, ");"); if(eov.is_error()){ return eov; } } - /** - * Continue if elements remain or finish - */ - if constexpr ( (i+1) < sizeof...(Funcs) ){ - return generate_ele(state); + if constexpr ((i+1) < sizeof...(M) ){ + return generate_element(buff, cfg, 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()); - state.template get<"crc32">().set(schema_hash::apply()); - }catch(const std::exception&){ - return make_error(); + static error_or generate(buffer& buff, const language_binding_config& cfg){ + if(cfg.prefix.size() == 0){ + return make_error("C interfaces need a prefix."); } - - if constexpr (sizeof...(Funcs) > 0){ - return generate_ele<0>(state); + language_binding_state state; + + if constexpr (sizeof...(M) > 0){ + return generate_element<0>(buff, cfg, state); } + return void_t{}; } }; - -template -error_or generate_c_interface(data& state){ - auto eov = c_data_translater::generate(state); - return eov; -} -/* -namespace lang { -struct C {}; } -template -class binding; +template +struct language_binding { + static_assert(always_false, "Case not supported."); +}; -template -class binding { -public: - static constexpr string_literal header; - static constexpr string_literal source; +template +struct language_binding { + static error_or generate(buffer& buff, const language_binding_config& cfg){ + return impl::lang_bind::generate(buff, cfg); + } }; -*/ } -- cgit v1.2.3