diff --git a/include/blocks/block.h b/include/blocks/block.h index 6bcf46d..9830379 100644 --- a/include/blocks/block.h +++ b/include/blocks/block.h @@ -29,6 +29,20 @@ std::shared_ptr to(std::shared_ptr p) { return ret; } +template +std::shared_ptr clone(std::shared_ptr p) { + if (!p) return nullptr; + return to(p->clone_impl()); +} + +template +std::shared_ptr clone_obj(T* t) { + auto np = std::make_shared(); + np->static_offset = t->static_offset; + np->metadata_map = t->metadata_map; + return np; +} + template class block_metadata_impl; @@ -62,6 +76,8 @@ class block_metadata_impl : public block_metadata { block_metadata_impl(T _val) : val(_val) {} }; + + class block : public std::enable_shared_from_this { public: virtual ~block() = default; @@ -113,6 +129,11 @@ class block : public std::enable_shared_from_this { return false; return true; } + + virtual block::Ptr clone_impl(void) { + // abstract class always returns nullptr + return nullptr; + } }; } // namespace block #endif diff --git a/include/blocks/expr.h b/include/blocks/expr.h index 655d773..b24f07a 100644 --- a/include/blocks/expr.h +++ b/include/blocks/expr.h @@ -70,6 +70,23 @@ class binary_expr : public expr { return binary_is_same(self(), other); } }; + + +template +std::shared_ptr unary_clone_helper(T* t) { + auto np = clone_obj(t); + np->expr1 = clone(t->expr1); + return np; +} + +template +std::shared_ptr binary_clone_helper(T* t) { + auto np = clone_obj(t); + np->expr1 = clone(t->expr1); + np->expr2 = clone(t->expr2); + return np; +} + // For the logical not operator class not_expr : public unary_expr { public: @@ -81,6 +98,9 @@ class not_expr : public unary_expr { virtual bool is_same(block::Ptr other) override { return unary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return unary_clone_helper(this); + } }; // For the unary minus operator class unary_minus_expr : public unary_expr { @@ -93,6 +113,9 @@ class unary_minus_expr : public unary_expr { virtual bool is_same(block::Ptr other) override { return unary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return unary_clone_helper(this); + } }; // For the bitwise not operator class bitwise_not_expr : public unary_expr { @@ -105,6 +128,9 @@ class bitwise_not_expr : public unary_expr { virtual bool is_same(block::Ptr other) override { return unary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return unary_clone_helper(this); + } }; class and_expr : public binary_expr { @@ -117,6 +143,9 @@ class and_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class bitwise_and_expr : public binary_expr { @@ -129,6 +158,9 @@ class bitwise_and_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class or_expr : public binary_expr { @@ -141,6 +173,9 @@ class or_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class bitwise_or_expr : public binary_expr { @@ -153,6 +188,9 @@ class bitwise_or_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class bitwise_xor_expr : public binary_expr { @@ -165,6 +203,9 @@ class bitwise_xor_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class plus_expr : public binary_expr { @@ -177,6 +218,9 @@ class plus_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class minus_expr : public binary_expr { @@ -189,6 +233,9 @@ class minus_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class mul_expr : public binary_expr { @@ -201,6 +248,9 @@ class mul_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class div_expr : public binary_expr { @@ -213,6 +263,9 @@ class div_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class lt_expr : public binary_expr { public: @@ -224,6 +277,9 @@ class lt_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class gt_expr : public binary_expr { public: @@ -235,6 +291,9 @@ class gt_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class lte_expr : public binary_expr { public: @@ -246,6 +305,9 @@ class lte_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class gte_expr : public binary_expr { public: @@ -257,6 +319,9 @@ class gte_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class lshift_expr : public binary_expr { public: @@ -268,6 +333,9 @@ class lshift_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class rshift_expr : public binary_expr { public: @@ -279,6 +347,9 @@ class rshift_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class equals_expr : public binary_expr { public: @@ -290,6 +361,9 @@ class equals_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class ne_expr : public binary_expr { @@ -302,6 +376,9 @@ class ne_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class mod_expr : public binary_expr { @@ -314,6 +391,9 @@ class mod_expr : public binary_expr { virtual bool is_same(block::Ptr other) override { return binary_is_same(self(), other); } + virtual block::Ptr clone_impl(void) override { + return binary_clone_helper(this); + } }; class var_expr : public expr { public: @@ -332,6 +412,13 @@ class var_expr : public expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + // Vars are special cases and should not be cloned + // This is to avoid problems where vars are compared by pointers + np->var1 = var1; + return np; + } }; class const_expr : public expr { @@ -368,6 +455,12 @@ class int_const : public const_expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->value = value; + np->is_64bit = is_64bit; + return np; + } }; class double_const : public const_expr { public: @@ -387,6 +480,12 @@ class double_const : public const_expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->value = value; + return np; + } + }; class float_const : public const_expr { public: @@ -406,6 +505,11 @@ class float_const : public const_expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->value = value; + return np; + } }; class string_const : public const_expr { @@ -426,6 +530,11 @@ class string_const : public const_expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->value = value; + return np; + } }; class assign_expr : public expr { @@ -449,6 +558,12 @@ class assign_expr : public expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->var1 = clone(var1); + np->expr1 = clone(expr1); + return np; + } }; class sq_bkt_expr : public expr { public: @@ -470,6 +585,12 @@ class sq_bkt_expr : public expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->var_expr = clone(var_expr); + np->index = clone(index); + return np; + } }; class function_call_expr : public expr { public: @@ -496,6 +617,14 @@ class function_call_expr : public expr { } return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->expr1 = clone(expr1); + for (auto arg: args) { + np->args.push_back(clone(arg)); + } + return np; + } }; class initializer_list_expr : public expr { @@ -519,6 +648,13 @@ class initializer_list_expr : public expr { } return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + for (auto elem: elems) { + np->elems.push_back(clone(elem)); + } + return np; + } }; // We first implement a base class for foreign_expr for visitor purposes @@ -558,6 +694,11 @@ class foreign_expr : public foreign_expr_base { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->inner_expr = inner_expr; + return np; + } }; class member_access_expr : public expr { @@ -580,6 +721,12 @@ class member_access_expr : public expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->parent_expr = clone(parent_expr); + np->member_name = member_name; + return np; + } }; class addr_of_expr : public expr { @@ -599,6 +746,11 @@ class addr_of_expr : public expr { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_obj(this); + np->expr1 = clone(expr1); + return np; + } }; } // namespace block diff --git a/include/blocks/stmt.h b/include/blocks/stmt.h index a0403b5..c1f9794 100644 --- a/include/blocks/stmt.h +++ b/include/blocks/stmt.h @@ -19,6 +19,13 @@ class stmt : public block { } }; +template +std::shared_ptr clone_stmt(T* t) { + auto np = clone_obj(t); + np->annotation = t->annotation; + return np; +} + class expr_stmt : public stmt { public: typedef std::shared_ptr Ptr; @@ -41,6 +48,13 @@ class expr_stmt : public stmt { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_stmt(this); + np->expr1 = clone(expr1); + np->mark_for_deletion = mark_for_deletion; + return np; + } + }; class stmt_block : public stmt { @@ -65,6 +79,13 @@ class stmt_block : public stmt { } return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_stmt(this); + for (auto stmt: stmts) { + np->stmts.push_back(clone(stmt)); + } + return np; + } }; class decl_stmt : public stmt { @@ -94,6 +115,17 @@ class decl_stmt : public stmt { return false; return true; } + virtual block::Ptr clone_impl(void) override { + auto np = clone_stmt(this); + // Vars are not to be cloned because + // they are compared by pointers sometimes + + // If we _do_ end up duplicating them, + // they should be consistently updated + np->decl_var = decl_var; + np->init_expr = clone(init_expr); + return np; + } }; class if_stmt : public stmt { @@ -132,6 +164,13 @@ class if_stmt : public stmt { return true; assert(false && "Statement unreachable"); } + virtual block::Ptr clone_impl(void) override { + auto np = clone_stmt(this); + np->cond = clone(cond); + np->then_stmt = clone(then_stmt); + np->else_stmt = clone(else_stmt); + return np; + } }; class label : public block { public: @@ -149,6 +188,11 @@ class label : public block { return false; return true; } + virtual block::Ptr clone_impl(void) override { + // Don't duplicate labels + // just like vars these might be compared by ptr + return self