summaryrefslogtreecommitdiff
path: root/modules/tools/c++
diff options
context:
space:
mode:
Diffstat (limited to 'modules/tools/c++')
-rw-r--r--modules/tools/c++/c_gen_iface.hpp474
1 files changed, 144 insertions, 330 deletions
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 <iostream>
namespace saw {
-
-namespace schema {
-
-using CVar = Struct<
- Member<schema::String, "schema">,
- Member<schema::UInt32, "crc32">,
- Member<schema::String, "type">,
- Member<schema::String, "type_name">,
- Member<schema::String, "name">,
- Member<schema::Int8, "is_primitive">
->;
-
-using CStruct = Struct<
- Member<schema::String, "schema">,
- Member<schema::UInt32, "crc32">,
- Member<schema::String, "type">,
- Member<Array<CVar>, "members">
->;
-
-using CFunction = Struct<
- Member<schema::String, "schema">,
- Member<schema::UInt32, "crc32">,
- Member<schema::String, "name">,
- Member<Array<CVar>, "params">,
- Member<CVar, "return">
->;
-
-using CIface = Struct<
- Member<schema::String, "schema">,
- Member<schema::UInt32, "crc32">,
- Member<Array<CStruct>,"structs">,
- Member<Array<CFunction>,"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<Array<Int32>, "a">
- Member<Array<Float32>, "b">
->;
-
-Needs to be flattened to
-
-template<typename InnerSchema>
-using FlattenedSchemaElement = Struct<
- Member<Array<String>, "path">,
- Member<InnerSchema, "inner_schema">
->;
-
-// Illegal, but doable with more lines of code
-// Just use typename... T and
-// "T..." for
-// "Member<FlattenedSchemaElement<Ele>,Names>...>"
-// and specialize somewhere else
-template<typename... Ele, string_literal... Names>
-using FlattenedSchema = Struct<
- Member<String, "top_schema">,
- Member<FlattenedSchemaElement<Ele>, Names>...
->;
+namespace binding {
+struct C {};
}
-*/
-
-template<typename T, typename Res>
-struct schema_flattener {
- static_assert(always_false<T>, "Not supported");
-};
-
-template<typename T0, string_literal Name0, typename... T, string_literal... Names, typename Res>
-struct schema_flattener<schema::Struct<schema::Member<T0,Name0>,schema::Member<T,Names>...>, Res> {
-};
/**
* Helper to determine if we are dealing with primitive types
@@ -166,336 +94,222 @@ struct c_primitive_string<schema::Float64> {
static constexpr string_literal value = "double";
};
-error_or<data<schema::UInt64>> c_interface_find_struct_by_crc32(const data<schema::CIface>& state, const data<schema::UInt32>& 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<schema::UInt64>{i};
- }
- }
- return make_error<err::not_found>();
-}
-
-error_or<void> c_interface_add_struct(data<schema::CIface>& state, data<schema::CStruct>&& 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<schema::CIface>& 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<typename Schema>
-struct c_data_translater {
+namespace impl {
+template<typename Schema, typename Lang>
+struct lang_bind {
static_assert(always_false<Schema>, "Not supported");
};
-template<typename T, uint64_t N>
-struct c_data_translater<schema::Primitive<T,N>> {
- using Schema = schema::Primitive<T,N>;
- static constexpr string_literal c_type_name = c_primitive_string<Schema>::name;
- static constexpr string_literal c_type = c_primitive_string<Schema>::value;
-
- static error_or<void> generate(data<schema::CIface>& state, data<schema::CVar>& prim){
- try{
- std::stringstream iss;
- schema_stringify<Schema>::apply(iss);
- prim.template get<"schema">().set(iss.str());
- prim.template get<"crc32">().set(schema_hash<Schema>::apply());
- prim.template get<"is_primitive">().set(1);
- prim.template get<"type">().set(std::string{c_primitive_string<Schema>::value.view()});
- }catch(const std::exception&){
- return make_error<err::out_of_memory>();
+struct language_binding_state {
+ struct info {
+ std::string type;
+ };
+ std::map<uint32_t, language_binding_state::info> hashes;
+};
+
+struct lang_bind_helper {
+ static error_or<void> append_string(buffer& buff, const std::string_view& str){
+ for(uint64_t i = 0; i < str.size(); ++i){
+ auto err = buff.push(static_cast<uint8_t>(str[i]));
+ if(!err.template is_type<err::no_error>()){
+ return err;
+ }
}
+ return void_t{};
+ }
+ static error_or<void> 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<typename T, uint64_t N>
-struct c_data_translater<schema::Array<T,N>> {
- static_assert(N==1, "Doesn't support more than one dimension currently");
-
- using Schema = schema::Array<T,N>;
- static constexpr string_literal c_type_name = "array_"_sl + c_data_translater<T>::c_type_name + "_1d"_sl;
- static constexpr string_literal c_type = c_type_name + "_t"_sl;
-
- static error_or<void> generate(data<schema::CIface>& state, data<schema::CVar>& arr){
- try{
- {
- std::stringstream iss;
- schema_stringify<Schema>::apply(iss);
- arr.template get<"schema">().set(iss.str());
- arr.template get<"crc32">().set(schema_hash<Schema>::apply());
- arr.template get<"is_primitive">().set(0);
- }
+template<typename T, uint64_t L>
+struct lang_bind<schema::Primitive<T,L>, binding::C> {
+ using Schema = schema::Primitive<T,L>;
- /// @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<void> generate(buffer& buff, 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";
+ 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<schema::CStruct> 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<schema::CVar> c_var;
- std::stringstream iss;
- schema_stringify<T>::apply(iss);
- c_var.template get<"schema">().set(iss.str());
- c_var.template get<"crc32">().set(schema_hash<T>::apply());
- if constexpr (is_primitive<T>::value){
- c_var.template get<"type">().set(std::string{c_primitive_string<T>::value.view()} + "*");
- c_var.template get<"name">().set(std::string{"data"});
- c_var.template get<"is_primitive">().set(1);
- }else{
- return make_error<err::not_implemented>();
- }
-
- 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<Schema>::value.view());
+ if(eov.is_error()){
+ return eov;
}
- {
- data<schema::CVar> c_var;
- std::stringstream iss;
- schema_stringify<schema::UInt64>::apply(iss);
- c_var.template get<"schema">().set(iss.str());
- c_var.template get<"crc32">().set(schema_hash<schema::UInt64>::apply());
- if constexpr (is_primitive<T>::value){
- c_var.template get<"type">().set(std::string{c_primitive_string<schema::UInt64>::value.view()});
- c_var.template get<"name">().set(std::string{"size"});
- c_var.template get<"is_primitive">().set(1);
- }else{
- return make_error<err::not_implemented>();
- }
-
- 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<err::out_of_memory>();
}
return void_t{};
}
};
-/*
-template<typename... Members>
-struct c_data_translater<schema::Struct<Members...>> {
- using Schema = schema::Struct<Members...>;
-
- static error_or<void> generate(data<schema::CIface>& state){
- return void_t{};
- }
-};
-*/
-
-template<typename Str>
-struct c_parameter_translater {
- static_assert(always_false<Str>, "Type not supported");
-};
-
-template<typename... V, string_literal... K>
-struct c_parameter_translater<schema::Struct<schema::Member<V,K>...>> {
- template<uint64_t i>
- static error_or<void> generate_ele(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){
- using Type = typename parameter_pack_type<i, V...>::type;
- constexpr string_literal Literal = parameter_key_pack_type<i,K...>::literal;
+template<typename Input, typename Output>
+struct lang_bind<schema::Function<Input, Output>, binding::C> {
+ static error_or<void> generate(buffer& buff, const language_binding_config& cfg, language_binding_state& state){
+ constexpr uint64_t input_hash = schema_hash<Input>::apply();
+ constexpr uint64_t output_hash = schema_hash<Output>::apply();
{
- auto c_var = data<schema::CVar>{};
- c_var.template get<"name">().set(std::string{Literal.view()});
- {
- auto eov = c_data_translater<Type>::generate(state,c_var);
+ auto eov = lang_bind<Input, binding::C>::generate(buff, cfg, state);
if(eov.is_error()){
return eov;
}
- }
- {
- auto eov = params.add(std::move(c_var));
+ }
+ {
+ auto eov = lang_bind<Output, binding::C>::generate(buff, cfg, state);
if(eov.is_error()){
return eov;
}
- }
}
- if constexpr ( (i+1) < sizeof...(V) ) {
- return generate_ele<i+1>(state, params);
- }
- return void_t{};
- }
-
- static error_or<void> generate(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){
- if constexpr ( sizeof...(V) > 0){
- return generate_ele<0>(state, params);
- }
return void_t{};
}
};
-template<typename Req, typename Ret>
-struct c_data_translater<schema::Function<Req,Ret>> {
- using Schema = schema::Function<Req,Ret>;
-
- static error_or<void> generate_struct_params(data<schema::CIface>& state, data<schema::Array<schema::CVar>>& params){
- return c_parameter_translater<Req>::generate(state, params);
- }
+template<typename... M>
+struct lang_bind<schema::Interface<M...>, binding::C> {
+ template<uint64_t i>
+ static error_or<void> generate_element(buffer& buff, 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;
- static error_or<void> generate(data<schema::CIface>& state, const std::string_view& func_name){
- if(c_interface_function_exists(state, func_name)){
- return make_error<err::invalid_state>("Function already exists");
+ {
+ auto eov = lang_bind<MValue, binding::C>::generate(buff, cfg, state);
+ if(eov.is_error()){
+ return eov;
+ }
}
- auto& funcs = state.template get<"functions">();
- data<schema::CFunction> function;
- function.template get<"name">().set(std::string{func_name});
-
- try{
- std::stringstream iss;
- schema_stringify<Schema>::apply(iss);
- function.template get<"schema">().set(iss.str());
- function.template get<"crc32">().set(schema_hash<Schema>::apply());
- }catch(const std::exception&){
- return make_error<err::out_of_memory>();
+ {
+ 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<Ret>::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<Req>::value){
- auto c_var = data<schema::CVar>{};
- c_var.template get<"name">().set("req_val");
- {
- auto eov = c_data_translater<Req>::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<Member>::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<typename... Funcs, string_literal... Names>
-struct c_data_translater<schema::Interface<schema::Member<Funcs,Names>...>> {
- using Schema = schema::Interface<schema::Member<Funcs, Names>...>;
-
- template<std::size_t i>
- static error_or<void> generate_ele(data<schema::CIface>& state){
- using InnerSchema = typename parameter_pack_type<i, Funcs...>::type;
- constexpr string_literal Literal = parameter_key_pack_type<i, Names...>::literal;
{
- auto eov = c_data_translater<InnerSchema>::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<i+1>(state);
+ if constexpr ((i+1) < sizeof...(M) ){
+ return generate_element<i+1>(buff, cfg, state);
}
return void_t{};
}
- static error_or<void> generate(data<schema::CIface>& state){
- try{
- std::stringstream iss;
- schema_stringify<Schema>::apply(iss);
- state.template get<"schema">().set(iss.str());
- state.template get<"crc32">().set(schema_hash<Schema>::apply());
- }catch(const std::exception&){
- return make_error<err::out_of_memory>();
+ static error_or<void> generate(buffer& buff, const language_binding_config& cfg){
+ if(cfg.prefix.size() == 0){
+ return make_error<err::invalid_state>("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<typename Interface>
-error_or<void> generate_c_interface(data<schema::CIface>& state){
- auto eov = c_data_translater<Interface>::generate(state);
- return eov;
-}
-/*
-namespace lang {
-struct C {};
}
-template<typename Iface, typename T>
-class binding;
+template<typename IfaceSchema, typename Binding>
+struct language_binding {
+ static_assert(always_false<IfaceSchema, Binding>, "Case not supported.");
+};
-template<typename Iface>
-class binding<Iface, lang::C> {
-public:
- static constexpr string_literal header;
- static constexpr string_literal source;
+template<typename IfaceSchema>
+struct language_binding<IfaceSchema, binding::C> {
+ static error_or<void> generate(buffer& buff, const language_binding_config& cfg){
+ return impl::lang_bind<IfaceSchema, binding::C>::generate(buff, cfg);
+ }
};
-*/
}