From 76a296cf1eb56966ea3783843d66a1dfa7058ad2 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Thu, 4 Apr 2024 23:42:20 -0400 Subject: [PATCH] Added support for auto custom type and members --- include/builder/block_type_extractor.h | 52 ++++++++++++++++++++++++-- include/builder/dyn_var.h | 41 +++++++++++++++++++- samples/sample56.cpp | 44 ++++++++++++++++++++++ src/builder/block_type_extractor.cpp | 5 +++ 4 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 samples/sample56.cpp create mode 100644 src/builder/block_type_extractor.cpp diff --git a/include/builder/block_type_extractor.h b/include/builder/block_type_extractor.h index 15a9d8a..212018d 100644 --- a/include/builder/block_type_extractor.h +++ b/include/builder/block_type_extractor.h @@ -8,6 +8,50 @@ namespace builder { struct custom_type_base; + + +template +struct check_valid_type { + typedef void type; +}; + +extern int type_naming_counter; + +template +struct type_namer { + static std::string obtained_name; + static std::string get_type_name() { + if (obtained_name == "") { + obtained_name = "custom_struct" + std::to_string(type_naming_counter++); + } + return obtained_name; + } +}; +template +std::string type_namer::obtained_name = ""; + +template +struct type_namer::type> { + static std::string get_type_name() { + return T::type_name; + } +}; + +template +struct type_template { + static std::vector get_templates() { + return {}; + } +}; + +template +struct type_template::type> { + static std::vector get_templates() { + return T::get_template_arg_types(); + } +}; + + // The main definition of the type extractor classes template class type_extractor { @@ -15,11 +59,11 @@ class type_extractor { // This implementation is currenty only used // by custom types which are derived from custom_type_base static block::type::Ptr extract_type(void) { - static_assert(std::is_base_of::value, - "Custom types should inherit from builder::custom_type_base"); + //static_assert(std::is_base_of::value, + //"Custom types should inherit from builder::custom_type_base"); block::named_type::Ptr type = std::make_shared(); - type->type_name = T::type_name; - type->template_args = T::get_template_arg_types(); + type->type_name = type_namer::get_type_name(); + type->template_args = type_template::get_templates(); return type; } }; diff --git a/include/builder/dyn_var.h b/include/builder/dyn_var.h index 9cf35ac..0c64872 100644 --- a/include/builder/dyn_var.h +++ b/include/builder/dyn_var.h @@ -35,6 +35,8 @@ class var { // Feature to gather members of this type std::vector members; + // Counter for naming unnamed members + int member_counter = 0; static block::type::Ptr create_block_type(void) { // Cannot create block type for abstract class @@ -146,6 +148,22 @@ class dyn_var_impl : public var { } dyn_var_impl() { + // implementation for auto member detection + if (parents_stack && parents_stack->size() != 0) { + current_state = member_var; + parent_var = parents_stack->back(); + var_name = "mem" + std::to_string(parent_var->member_counter++); + block_var = nullptr; + block_decl_stmt = nullptr; + + if (options::track_members) { + parent_var->members.push_back(this); + block_var = std::make_shared(); + block_var->var_type = create_block_type(); + block_var->var_name = var_name; + } + return; + } create_dyn_var(false); } // Basic and other constructors @@ -165,6 +183,21 @@ class dyn_var_impl : public var { *ptr_to_leak = block_var; } dyn_var_impl(const with_name &v) { + if (parents_stack && parents_stack->size() != 0) { + current_state = member_var; + parent_var = parents_stack->back(); + var_name = v.name; + block_var = nullptr; + block_decl_stmt = nullptr; + + if (options::track_members) { + parent_var->members.push_back(this); + block_var = std::make_shared(); + block_var->var_type = create_block_type(); + block_var->var_name = var_name; + } + return; + } // with_name constructors don't usually get declarations create_dyn_var(!v.with_decl); block_var->var_name = v.name; @@ -174,6 +207,8 @@ class dyn_var_impl : public var { dyn_var_impl(const defer_init &) { // Do nothing here + // Defer init "automatically" supports custom types + // because well, we don't create declarations anyway } // The function to actually initialize a dyn_var, if it // has been deferred. It is OKAY to call this even if defer_init @@ -302,7 +337,11 @@ struct member_initializer_end { }; template -struct dyn_var_parent_selector::value>::type> +struct dyn_var_parent_selector::value && !std::is_base_of::value + && !std::is_base_of::value + >::type> : public member_initializer_begin, public T, public member_initializer_end {}; // Actual dyn_var implementation diff --git a/samples/sample56.cpp b/samples/sample56.cpp new file mode 100644 index 0000000..9ca4fe5 --- /dev/null +++ b/samples/sample56.cpp @@ -0,0 +1,44 @@ +#include "blocks/c_code_generator.h" +#include "builder/builder.h" +#include "builder/builder_context.h" +#include "builder/dyn_var.h" +#include "builder/static_var.h" +#include + +using builder::as_member; +using builder::dyn_var; +using builder::static_var; + + +struct struct_type { + dyn_var x; + dyn_var y; +}; + +struct my_type { + static constexpr const char* type_name = "my_type"; + dyn_var nested = builder::with_name("nested"); + dyn_var another; +}; + +static void bar(void) { + dyn_var a; + dyn_var b; + + a.nested = b; + a.nested.x = a.another; + + a.nested.y++; +} + +int main(int argc, char *argv[]) { + + builder::builder_context context; + auto ast = context.extract_function_ast(bar, "bar"); + ast->dump(std::cout, 0); + + block::c_code_generator::generate_struct_decl>(std::cout); + block::c_code_generator::generate_struct_decl>(std::cout); + block::c_code_generator::generate_code(ast, std::cout, 0); + return 0; +} diff --git a/src/builder/block_type_extractor.cpp b/src/builder/block_type_extractor.cpp new file mode 100644 index 0000000..2d14da6 --- /dev/null +++ b/src/builder/block_type_extractor.cpp @@ -0,0 +1,5 @@ +#include "builder/block_type_extractor.h" + +namespace builder { +int type_naming_counter = 0; +}