summaryrefslogtreecommitdiff
path: root/modules/tools
diff options
context:
space:
mode:
Diffstat (limited to 'modules/tools')
-rw-r--r--modules/tools/c++/c_gen_iface.hpp472
-rw-r--r--modules/tools/tests/c_iface.cpp10
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">
>;
}