diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-03-27 16:21:39 +0100 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2024-03-27 16:21:39 +0100 |
commit | 558c6b333f96dc4953337fa9e290b36fbbce5bc3 (patch) | |
tree | 627d4c7daf979e142c75e2d0b9a65a0de8bb749c | |
parent | cdd8dab6d276d8b62b025ac98e495a258331d1e6 (diff) |
tools: Changing transpiling and adding structs
-rw-r--r-- | modules/tools/c++/c_gen_iface.hpp | 472 | ||||
-rw-r--r-- | modules/tools/tests/c_iface.cpp | 10 |
2 files changed, 309 insertions, 173 deletions
diff --git a/modules/tools/c++/c_gen_iface.hpp b/modules/tools/c++/c_gen_iface.hpp index 15d9497..e70479d 100644 --- a/modules/tools/c++/c_gen_iface.hpp +++ b/modules/tools/c++/c_gen_iface.hpp @@ -120,6 +120,31 @@ struct language_binding_state { std::string source; }; std::vector<language_binding_state::transpiled_element> tp_elements; + + error_or<uint64_t> find_id_by_crc32(uint32_t hash){ + for(uint64_t iter = 0; iter < tp_elements.size(); ++iter){ + if(tp_elements.at(iter).crc32 == hash){ + return iter; + } + } + return make_error<err::not_found>(); + } + + error_or<uint64_t> add_tp_element(uint32_t hash){ + uint64_t id{}; + try{ + language_binding_state::transpiled_element ele; + + ele.crc32 = hash; + + id = tp_elements.size(); + tp_elements.emplace_back(std::move(ele)); + }catch(const std::exception&){ + return make_error<err::out_of_memory>(); + } + + return id; + } }; struct lang_bind_helper { @@ -166,6 +191,7 @@ template<typename T, uint64_t L> struct lang_bind<schema::Primitive<T,L>, binding::SyncC> { using Schema = schema::Primitive<T,L>; +/* static error_or<void> generate_c_to_cpp(const language_binding_config& cfg, language_binding_state& state, const std::string_view& cpp_name, const std::string_view& c_name ){ return void_t{}; { @@ -236,47 +262,52 @@ struct lang_bind<schema::Primitive<T,L>, binding::SyncC> { return void_t{}; } - - static error_or<void> generate(buffer& head, buffer& src, const language_binding_config& cfg, language_binding_state& state){ +*/ + static error_or<void> generate(const language_binding_config& cfg, language_binding_state& state){ constexpr uint32_t hash = schema_hash<Schema>::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){ - try { - language_binding_state::transpiled_element ele; - ele.crc32 = hash; - state.tp_elements.emplace_back(ele); - }catch(const std::exception&){ - return make_error<err::out_of_memory>(); + /** + * We want this id to access the vector + */ + auto& tpe = state.tp_elements; + uint64_t id; + { + auto eoid = state.add_tp_element(hash); + if(eoid.is_error()){ + return std::move(eoid.get_error()); + } + id = eoid.get_value(); } { - auto eov = lang_bind_helper::append_string(head, "typedef "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "typedef "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, c_primitive_string<Schema>::value.view()); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, c_primitive_string<Schema>::value.view()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, " "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, hash_type_str); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, hash_type_str); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, ";\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, ";\n"); if(eov.is_error()){ return eov; } @@ -292,70 +323,65 @@ template<typename... V, string_literal... K> struct lang_bind<schema::Struct<schema::Member<V,K>...>, binding::SyncC> { using Schema = schema::Struct<schema::Member<V,K>...>; - static error_or<void> generate_c_to_cpp(buffer& src, const language_binding_config& cfg, language_binding_state& state, const std::string_view& cpp_name, const std::string_view& c_name ){ - return void_t{}; - } - - static error_or<void> generate_cpp_to_c(buffer& src, const language_binding_config& cfg, language_binding_state& state, const std::string_view& c_name, const std::string_view& cpp_name ){ - return void_t{}; - } - template<uint64_t i> - static error_or<void> guarantee_ele(buffer& head, buffer& src, const language_binding_config& cfg, language_binding_state& state){ + static error_or<void> generate_ele(const language_binding_config& cfg, language_binding_state& state, int64_t id){ using MT = typename parameter_pack_type<i,V...>::type; + static constexpr string_literal Lit = parameter_key_pack_type<i,K...>::literal; + + constexpr uint32_t hash = schema_hash<MT>::apply(); + /** - * Guarante existance of inner type + * Generate struct member definition. */ + auto& tpe = state.tp_elements; + { - auto eov = lang_bind<MT, binding::SyncC>::generate(head, src, cfg, state); - if(eov.is_error()){ - return eov; - } + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "\t"); + if(eov.is_error()){ + return eov; + } } - if constexpr ( (i+1) < sizeof...(V) ){ - return guarantee_ele<i+1u>(head, src, cfg, state); + { + auto eov = lang_bind_helper::append_hashed_type(tpe.at(id).header, cfg.prefix, hash); + if(eov.is_error()){ + return eov; + } } - return void_t{}; - } - - template<uint64_t i> - static error_or<void> generate_ele(buffer& head, buffer& src, const language_binding_config& cfg, language_binding_state& state){ - using MT = typename parameter_pack_type<i,V...>::type; - static constexpr string_literal Lit = parameter_key_pack_type<i,K...>::literal; - - constexpr uint64_t hash = schema_hash<MT>::apply(); { - auto eov = lang_bind_helper::append_hashed_type(head, cfg.prefix, hash); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, " "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, Lit.view()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, Lit.view()); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, ";\n"); if(eov.is_error()){ return eov; } } + /** + * Ensure generation of dependent types + */ { - auto eov = lang_bind_helper::append_string(head, ";\n"); + auto eov = lang_bind<MT, binding::SyncC>::generate(cfg, state); if(eov.is_error()){ return eov; } } if constexpr ( (i+1) < sizeof...(V) ){ - return generate_ele<i+1u>(head, src, cfg, state); + return generate_ele<i+1u>(cfg, state, id); } return void_t{}; } - static error_or<void> generate(buffer& head, buffer& src, const language_binding_config& cfg, language_binding_state& state){ + static error_or<void> generate(const language_binding_config& cfg, language_binding_state& state){ constexpr uint64_t hash = schema_hash<Schema>::apply(); std::string hash_type_str = cfg.prefix + "_" + std::to_string(hash) + "_t"; @@ -368,35 +394,38 @@ struct lang_bind<schema::Struct<schema::Member<V,K>...>, binding::SyncC> { /** * Generate struct type */ - if constexpr ( sizeof...(V) > 0){ - auto eov = guarantee_ele<0u>(head, src, cfg, state); - if(eov.is_error()){ - return eov; + auto& tpe = state.tp_elements; + uint64_t id; + { + auto eoid = state.add_tp_element(hash); + if(eoid.is_error()){ + return std::move(eoid.get_error()); } + id = eoid.get_value(); } { - auto eov = lang_bind_helper::append_string(head, "struct "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "struct "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(head, cfg.prefix, hash); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(id).header, cfg.prefix, hash); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, " {\n\t"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " {\n"); if(eov.is_error()){ return eov; } } if constexpr ( sizeof...(V) > 0 ) { - auto eov = generate_ele<0>(head, src, cfg, state); + auto eov = generate_ele<0>(cfg, state, id); } { - auto eov = lang_bind_helper::append_string(head, "};\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "};\n"); if(eov.is_error()){ return eov; } @@ -414,95 +443,102 @@ struct lang_bind<schema::Array<T,D>, binding::SyncC> { static_assert(is_primitive<T>::value, "Currently only primitive type arrays are supported"); - static error_or<void> generate_c_to_cpp(buffer& src, const language_binding_config& cfg, language_binding_state& state, const std::string_view& cpp_name, const std::string_view& c_name ){ - return void_t{}; - return make_error<err::not_implemented>(); - } - - static error_or<void> generate_cpp_to_c(buffer& src, const language_binding_config& cfg, language_binding_state& state, const std::string_view& c_name, const std::string_view& cpp_name ){ - return void_t{}; - return make_error<err::not_implemented>(); - } - - static error_or<void> generate(buffer& buff, buffer& src, const language_binding_config& cfg, language_binding_state& state){ - constexpr uint64_t hash = schema_hash<Schema>::apply(); + static error_or<void> generate(const language_binding_config& cfg, language_binding_state& state){ + constexpr uint32_t hash = schema_hash<Schema>::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){ - /** - * Guarante existance of length type - */ - { - auto eov = lang_bind<schema::UInt64, binding::SyncC>::generate(buff, src, cfg, state); - if(eov.is_error()){ - return eov; - } - } - /** - * Guarante existance of inner type - */ + + auto& tpe = state.tp_elements; + uint64_t id; { - auto eov = lang_bind<T, binding::SyncC>::generate(buff, src, cfg, state); - if(eov.is_error()){ - return eov; - } + auto eoid = state.add_tp_element(hash); + if(eoid.is_error()){ + return std::move(eoid.get_error()); + } + id = eoid.get_value(); } /** * Generate struct type */ { - auto eov = lang_bind_helper::append_string(buff, "struct "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "struct "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, hash); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(id).header, cfg.prefix, hash); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, " {\n\t"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " {\n\t"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash<T>::apply()); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(id).header, cfg.prefix, schema_hash<T>::apply()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "* data;\n\t"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "* data;\n\t"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash<schema::UInt64>::apply()); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(id).header, cfg.prefix, schema_hash<schema::UInt64>::apply()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, " length;\n};\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " length;\n};\n"); if(eov.is_error()){ return eov; } } + /** + * Guarante existance of length type + */ + { + auto eov = lang_bind<schema::UInt64, binding::SyncC>::generate(cfg, state); + if(eov.is_error()){ + return eov; + } + } + /** + * Guarante existance of inner type + */ + { + auto eov = lang_bind<T, binding::SyncC>::generate(cfg, state); + if(eov.is_error()){ + return eov; + } + } } return void_t{}; } }; +/** + * Generates the Function bindings to C + */ template<typename Input, typename Output> struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { - static error_or<void> append_function_def(buffer& buff, const language_binding_config& cfg, language_binding_state& state, const std::string_view& f_name){ + using Schema = schema::Function<Input, Output>; + /** + * Appends the function declaration e.g. 'int foo(const int* a, int* b)' + */ + static error_or<void> append_function_def(std::string& buff, const language_binding_config& cfg, language_binding_state& state, const std::string_view& f_name){ /** * Generate the base function declaration */ @@ -599,40 +635,70 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { return void_t{}; } + + static error_or<void> guarantee(const language_binding_config& cfg, language_binding_state& state){ + /** + * Ensure existence of input and output types. + * Order is not important since moving to multiple strings which get concat'ed. + */ + { + auto eov = lang_bind<Input, binding::SyncC>::generate(cfg, state); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = lang_bind<Output, binding::SyncC>::generate(cfg, state); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } - static error_or<void> generate(buffer& buff, buffer& src, const language_binding_config& cfg, language_binding_state& state, const std::string_view& f_name){ - constexpr uint64_t input_hash = schema_hash<Input>::apply(); + /** + * Hook for the interface lang_bind class. + * It's the only class which is out of place with its generate function. + * The issue being that it's deeply entrenched into the function names from the + * interface level. + * On one hand the Interface shouldn't generate the functions themselves. + * On the other hand the Functions need Interface information + */ + static error_or<void> generate(const language_binding_config& cfg, language_binding_state& state, const std::string_view& f_name, const uint64_t& f_id){ constexpr uint64_t output_hash = schema_hash<Output>::apply(); + auto& tpe = state.tp_elements; + /** * Source */ { - auto eov = append_function_def(src, cfg, state, f_name); + auto eov = append_function_def(tpe.at(f_id).source, cfg, state, f_name); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "{\n\tif(!ctx || !(ctx->ctx)) return -1;\n\tif(!input) return -1;\n\tif(!output) return -1;\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "{\n\tif(!ctx || !(ctx->ctx)) return -1;\n\tif(!input) return -1;\n\tif(!output) return -1;\n"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "\n\tauto& iface = "); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "\n\tauto& iface = "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "_get_cpp_interface_priv(*ctx);\n\t"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "_get_cpp_interface_priv(*ctx);\n\t"); if(eov.is_error()){ return eov; } @@ -642,7 +708,7 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { * Translate input. */ { - auto eov = lang_bind_helper::append_string(src, "saw::data<"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "saw::data<"); if(eov.is_error()){ return eov; } @@ -652,7 +718,7 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { try{ { schema_stringify<Input>::apply(ss); - auto eov = lang_bind_helper::append_string(src, ss.str()); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, ss.str()); if(eov.is_error()){ return eov; } @@ -662,19 +728,7 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { } } { - auto eov = lang_bind_helper::append_string(src, "> cpp_input_root;\n"); - if(eov.is_error()){ - return eov; - } - } - { - auto eov = lang_bind<Input, binding::SyncC>::generate(buff, src, cfg, state); - if(eov.is_error()){ - return eov; - } - } - { - auto eov = lang_bind<Input, binding::SyncC>::generate_c_to_cpp(src, cfg, state, "c_input_root", "cpp_input_root"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "> cpp_input_root;\n"); if(eov.is_error()){ return eov; } @@ -683,51 +737,35 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { * Call the c++ implementation */ { - auto eov = lang_bind_helper::append_string(src, "\n\tauto eov = iface.template call<\""); - if(eov.is_error()){ - return eov; - } - } - { - auto eov = lang_bind_helper::append_string(src, f_name); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "\n\tauto eov = iface.template call<\""); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "\">(std::move(cpp_input_root));\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, f_name); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "\tif(eov.is_error()){\n\t\tauto& err = eov.get_error();\n\t\treturn err.get_code();\n\t}\n\tauto& cpp_output_root = eov.get_value();\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "\">(std::move(cpp_input_root));\n"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind<Input, binding::SyncC>::generate_cpp_to_c(src, cfg, state, "cpp_output_root", "c_output_root"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "\tif(eov.is_error()){\n\t\tauto& err = eov.get_error();\n\t\treturn err.get_code();\n\t}\n\tauto& cpp_output_root = eov.get_value();\n\n"); if(eov.is_error()){ return eov; } } /** - * Check declarations and definitions. - * Translate output. - */ - { - auto eov = lang_bind<Output, binding::SyncC>::generate(buff, src, cfg, state); - if(eov.is_error()){ - return eov; - } - } - /** * End source declaration */ { - auto eov = lang_bind_helper::append_string(src, "\treturn 0;\n}\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).source, "\treturn 0;\n}\n\n"); if(eov.is_error()){ return eov; } @@ -736,85 +774,85 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { * Header */ { - auto eov = lang_bind_helper::append_string(buff, "typedef "); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "typedef "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash<Input>::apply()); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(f_id).header, cfg.prefix, schema_hash<Input>::apply()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, " "); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, " "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "_"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "_"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, f_name); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, f_name); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "_input_t;\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "_input_t;\n"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "typedef "); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "typedef "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_hashed_type(buff, cfg.prefix, schema_hash<Output>::apply()); + auto eov = lang_bind_helper::append_hashed_type(tpe.at(f_id).header, cfg.prefix, schema_hash<Output>::apply()); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, " "); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, " "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "_"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "_"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, f_name); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, f_name); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, "_output_t;\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, "_output_t;\n"); if(eov.is_error()){ return eov; } @@ -823,13 +861,13 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { * Function generations */ { - auto eov = append_function_def(buff, cfg, state, f_name); + auto eov = append_function_def(tpe.at(f_id).header, cfg, state, f_name); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(buff, ";\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(f_id).header, ";\n\n"); if(eov.is_error()){ return eov; } @@ -841,17 +879,54 @@ struct lang_bind<schema::Function<Input, Output>, binding::SyncC> { template<typename... M> struct lang_bind<schema::Interface<M...>, binding::SyncC> { + using Schema = schema::Interface<M...>; + + template<uint64_t i> + static error_or<void> guarantee_element(const language_binding_config& cfg, language_binding_state& state){ + using Member = typename parameter_pack_type<i, M...>::type; + using MValue = typename Member::ValueType; + { + /** + * Guarantee + */ + { + auto eov = lang_bind<MValue, binding::SyncC>::guarantee(cfg, state); + if(eov.is_error()){ + return eov; + } + } + } + + if constexpr ( (i+1u) < sizeof...(M) ){ + return guarantee_element<i+1u>(cfg, state); + } + return void_t{}; + } + template<uint64_t i> static error_or<void> generate_element(const language_binding_config& cfg, language_binding_state& state){ using Member = typename parameter_pack_type<i, M...>::type; using MValue = typename Member::ValueType; static constexpr string_literal MKey = Member::KeyLiteral; + constexpr uint64_t hash = schema_hash<Member>::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){ + return make_error<err::invalid_state>("Function should be guaranteed to be unique"); + } + + /** + * Adding Function to def + */ + uint64_t f_id; { - auto eov = lang_bind<MValue, binding::SyncC>::generate(cfg, state, MKey.view()); - if(eov.is_error()){ - return eov; + auto eoid = state.add_tp_element(hash); + if(eoid.is_error()){ + return std::move(eoid.get_error()); } + f_id = eoid.get_value(); } if constexpr ((i+1) < sizeof...(M) ){ @@ -864,22 +939,47 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { if(cfg.prefix.size() == 0){ return make_error<err::invalid_state>("C interfaces need a prefix."); } + constexpr uint64_t hash = schema_hash<Schema>::apply(); language_binding_state state; + + if constexpr (sizeof...(M) > 0){ + { + auto eov = generate_element<0>(cfg, state); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = guarantee_element<0>(cfg, state); + if(eov.is_error()){ + return eov; + } + } + } /** * Setup context creation to bind interface to a context */ + auto& tpe = state.tp_elements; + uint64_t id; + { + auto eoid = state.add_tp_element(hash); + if(eoid.is_error()){ + return std::move(eoid.get_error()); + } + id = eoid.get_value(); + } /** * Interface type helper */ { - auto eov = lang_bind_helper::append_string(src, "namespace {\nnamespace schema {\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, "namespace {\nnamespace schema {\n"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "using InterfaceType = "); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, "using InterfaceType = "); if(eov.is_error()){ return eov; } @@ -888,7 +988,7 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { std::stringstream ss; schema_stringify<schema::Interface<M...>>::apply(ss); try { - auto eov = lang_bind_helper::append_string(src, ss.str()); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, ss.str()); if(eov.is_error()){ return eov; } @@ -897,7 +997,7 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { } } { - auto eov = lang_bind_helper::append_string(src, ";\n}\n}\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, ";\n}\n}\n\n"); if(eov.is_error()){ return eov; } @@ -909,19 +1009,19 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { /// @todo Add Macro which reduces typing time ? Not really that much shorter :/ // SAW_CALL_AND_RETURN_ON_ERROR(lang_bind_helper::append_string(head, "struct ")); { - auto eov = lang_bind_helper::append_string(head, "struct "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "struct "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, "_context {\n\tvoid* ctx;\n};\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "_context {\n\tvoid* ctx;\n};\n\n"); if(eov.is_error()){ return eov; } @@ -931,43 +1031,43 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { */ auto ctx_func = [&](std::string_view str) -> error_or<void>{ { - auto eov = lang_bind_helper::append_string(head, "int "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "int "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, "_context_"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "_context_"); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, str); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, str); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, " ( "); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, " ( "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(head, "_context* ctx );\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).header, "_context* ctx );\n\n"); if(eov.is_error()){ return eov; } @@ -993,38 +1093,66 @@ struct lang_bind<schema::Interface<M...>, binding::SyncC> { * Create a casting helper in sources for the interface type */ { - auto eov = lang_bind_helper::append_string(src, "saw::interface<schema::InterfaceType>& "); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, "saw::interface<schema::InterfaceType>& "); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "_get_cpp_interface_priv("); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, "_get_cpp_interface_priv("); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, cfg.prefix); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, cfg.prefix); if(eov.is_error()){ return eov; } } { - auto eov = lang_bind_helper::append_string(src, "& ctx){\n\treturn *reinterpret_cast<saw::interface<schema::InterfaceType>*>(ctx.ctx);\n}\n\n"); + auto eov = lang_bind_helper::append_string(tpe.at(id).source, "& ctx){\n\treturn *reinterpret_cast<saw::interface<schema::InterfaceType>*>(ctx.ctx);\n}\n\n"); if(eov.is_error()){ return eov; } } - if constexpr (sizeof...(M) > 0){ - return generate_element<0>(head, src, cfg, state); + try{ + for(auto iter = state.tp_elements.rbegin(); iter != state.tp_elements.rend(); ++iter){ + for(auto c : iter->source){ + auto err = src.push(c); + if(!err.template is_type<err::no_error>()){ + return err; + } + } + { + auto err = src.push('\n'); + if(!err.template is_type<err::no_error>()){ + return err; + } + } + for(auto c : iter->header){ + auto err = head.push(c); + if(!err.template is_type<err::no_error>()){ + return err; + } + } + { + auto err = head.push('\n'); + if(!err.template is_type<err::no_error>()){ + return err; + } + } + } + } + catch(const std::exception&){ + return make_error<err::out_of_memory>(); } return void_t{}; diff --git a/modules/tools/tests/c_iface.cpp b/modules/tools/tests/c_iface.cpp index b70131e..35591f8 100644 --- a/modules/tools/tests/c_iface.cpp +++ b/modules/tools/tests/c_iface.cpp @@ -22,6 +22,13 @@ using TestStructArray = Struct< Member<TestArray, "array"> >; +using TestStructMore = Struct< + Member<Int64, "int">, + Member<UInt16, "uint">, + Member<Float32, "float">, + Member<Float64, "double"> +>; + using TestEmptyInterface = Interface<>; using TestOneFunctionInterface = Interface< @@ -44,7 +51,8 @@ using TestMultiFunctionInterface = Interface< Member<Function<TestArray, Float32>, "foo">, Member<Function<Float64, Int8>, "bar">, Member<Function<UInt32, TestArray>, "baz">, - Member<Function<UInt32, Float64>, "banana"> + Member<Function<UInt32, Float64>, "banana">, + Member<Function<TestStructMore, Float32>, "struct"> >; } |