From 026c01543fdc2041265257f913ef411e53611d41 Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Wed, 4 Dec 2024 18:13:31 -0500 Subject: [PATCH] Allow custom types to specify a dereference_type for operator[] --- include/builder/block_type_extractor.h | 5 ---- include/builder/dyn_var.h | 32 ++++++++++++++++++++++++-- include/builder/forward_declarations.h | 6 +++++ samples/outputs.var_names/sample59 | 29 +++++++++++++++++++++++ samples/outputs/sample59 | 29 +++++++++++++++++++++++ samples/sample59.cpp | 31 +++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 samples/outputs.var_names/sample59 create mode 100644 samples/outputs/sample59 create mode 100644 samples/sample59.cpp diff --git a/include/builder/block_type_extractor.h b/include/builder/block_type_extractor.h index 9bb2cd4..4373a85 100644 --- a/include/builder/block_type_extractor.h +++ b/include/builder/block_type_extractor.h @@ -10,11 +10,6 @@ struct custom_type_base; -template -struct check_valid_type { - typedef void type; -}; - extern int type_naming_counter; template diff --git a/include/builder/dyn_var.h b/include/builder/dyn_var.h index ca9c101..08dde56 100644 --- a/include/builder/dyn_var.h +++ b/include/builder/dyn_var.h @@ -344,10 +344,36 @@ struct dyn_var_parent_selector::type> : public member_initializer_begin, public std::remove_reference::type, public member_initializer_end {}; + +template +class dyn_var_mimic; + + +// These helper classes provide implementation of the operator[] +// The return type is selected based on whether the T has a member called dereference_type defined +// if it is defined, the return is builder::cast'd to a dyn_var (mimic) of that type (just like *) +// otherwise a regular builder return implementation is provided +// This allows implementation of vector<> types with appropriate return types +template +struct dyn_var_deref_provider { + builder operator[] (const builder& b) { + return static_cast*>(this)->dyn_var_impl::operator[](b); + } +}; + +template +struct dyn_var_deref_provider::type> { + dyn_var_mimic operator[] (const builder& b) { + return (cast)(static_cast*>(this)->dyn_var_impl::operator[](b)); + } +}; + + + // Actual dyn_var implementation // Split design to allow for easily extending types with specialization template -class dyn_var : public dyn_var_impl, public dyn_var_parent_selector { +class dyn_var : public dyn_var_impl, public dyn_var_parent_selector, public dyn_var_deref_provider { public: typedef dyn_var_impl super; @@ -366,10 +392,12 @@ class dyn_var : public dyn_var_impl, public dyn_var_parent_selector builder operator=(const dyn_var &t) { return *this = (builder)t; } + + using dyn_var_deref_provider::operator[]; }; -// dyn var specialization for pointer types to return the appropriate types on [], * and -> +// dyn var specialization for pointer types to return the appropriate types on [], * and -> template class dyn_var_mimic: public dyn_var { // Behaves exactly like a dyn_var for most purposes diff --git a/include/builder/forward_declarations.h b/include/builder/forward_declarations.h index 6d04413..dcfa0bf 100644 --- a/include/builder/forward_declarations.h +++ b/include/builder/forward_declarations.h @@ -60,6 +60,12 @@ struct with_name { with_name(const std::string &n, bool wd = false) : name(n), with_decl(wd) {} }; +template +struct check_valid_type { + typedef void type; +}; + + } // namespace builder #endif diff --git a/samples/outputs.var_names/sample59 b/samples/outputs.var_names/sample59 new file mode 100644 index 0000000..26a7f37 --- /dev/null +++ b/samples/outputs.var_names/sample59 @@ -0,0 +1,29 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + STMT_BLOCK + DECL_STMT + NAMED_TYPE (std::vector) + NAMED_TYPE (std::vector) + SCALAR_TYPE (INT) + VAR (x_0) + NO_INITIALIZATION + EXPR_STMT + FUNCTION_CALL_EXPR + MEMBER_ACCESS_EXPR (resize) + VAR_EXPR + VAR (x_0) + INT_CONST (2) + EXPR_STMT + FUNCTION_CALL_EXPR + MEMBER_ACCESS_EXPR (resize) + SQ_BKT_EXPR + VAR_EXPR + VAR (x_0) + INT_CONST (1) + INT_CONST (1) +void bar (void) { + std::vector> x_0; + x_0.resize(2); + (x_0[1]).resize(1); +} + diff --git a/samples/outputs/sample59 b/samples/outputs/sample59 new file mode 100644 index 0000000..3c3ab16 --- /dev/null +++ b/samples/outputs/sample59 @@ -0,0 +1,29 @@ +FUNC_DECL + SCALAR_TYPE (VOID) + STMT_BLOCK + DECL_STMT + NAMED_TYPE (std::vector) + NAMED_TYPE (std::vector) + SCALAR_TYPE (INT) + VAR (var0) + NO_INITIALIZATION + EXPR_STMT + FUNCTION_CALL_EXPR + MEMBER_ACCESS_EXPR (resize) + VAR_EXPR + VAR (var0) + INT_CONST (2) + EXPR_STMT + FUNCTION_CALL_EXPR + MEMBER_ACCESS_EXPR (resize) + SQ_BKT_EXPR + VAR_EXPR + VAR (var0) + INT_CONST (1) + INT_CONST (1) +void bar (void) { + std::vector> var0; + var0.resize(2); + (var0[1]).resize(1); +} + diff --git a/samples/sample59.cpp b/samples/sample59.cpp new file mode 100644 index 0000000..60b8942 --- /dev/null +++ b/samples/sample59.cpp @@ -0,0 +1,31 @@ +#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 "builder/lib/utils.h" +#include +using builder::dyn_var; +using builder::static_var; + + +template +struct vector: public builder::custom_type { + static constexpr const char* type_name = "std::vector"; + typedef T dereference_type; + dyn_var resize = builder::with_name("resize"); +}; + +static void bar(void) { + dyn_var>> x; + x.resize(2); + x[1].resize(1); +} + +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_code(ast, std::cout, 0); + return 0; +}