From 46147648024700877ee36133db9a5ba04e549a0b Mon Sep 17 00:00:00 2001 From: Ajay Brahmakshatriya Date: Sun, 2 Mar 2025 03:37:47 -0800 Subject: [PATCH] Support for richer patterns with var with names and function calls with arguments --- include/blocks/matchers/patterns.h | 18 +++++++++++++++--- src/blocks/matchers.cpp | 24 +++++++++++++++++++++--- src/blocks/replacers.cpp | 17 +++++++++++++++-- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/include/blocks/matchers/patterns.h b/include/blocks/matchers/patterns.h index bf03e10..3521c5f 100644 --- a/include/blocks/matchers/patterns.h +++ b/include/blocks/matchers/patterns.h @@ -79,10 +79,11 @@ struct pattern: public std::enable_shared_from_this { bool has_const = false; double const_val_double = 0; int const_val_int = 0; - std::string const_val_string = ""; - - // Constructor that assigns a name + std::string const_val_string = ""; + // In case of variable, the variable can be identified by specific names + std::string var_name; + // Constructor that assigns a name pattern(node_type t, std::string _name, std::vector _children) : type (t), name(_name), children(_children) {} pattern(node_type t, std::string _name): type(t), name(_name), children({}) {} @@ -394,6 +395,12 @@ static inline pattern::Ptr sq_bkt_expr(std::string name = "") { static inline pattern::Ptr function_call_expr(std::string name = "") { return std::make_shared(pattern::node_type::function_call_expr, name); } +static inline pattern::Ptr function_call_expr(pattern::Ptr x, std::vector y, std::string name = "") { + std::vector children; + children.push_back(x); + for (auto a: y) children.push_back(a); + return std::make_shared(pattern::node_type::function_call_expr, name, children); +} static inline pattern::Ptr initializer_list_expr(std::string name = "") { return std::make_shared(pattern::node_type::initializer_list_expr, name); } @@ -412,6 +419,11 @@ static inline pattern::Ptr addr_of_expr(pattern::Ptr x, std::string name = "") { static inline pattern::Ptr var(std::string name = "") { return std::make_shared(pattern::node_type::var, name); } +static inline pattern::Ptr var_with_name(std::string var_name, std::string name = "") { + auto p = std::make_shared(pattern::node_type::var, name); + p->var_name = var_name; + return p; +} static inline pattern::Ptr type(std::string name = "") { return std::make_shared(pattern::node_type::type, name); } diff --git a/src/blocks/matchers.cpp b/src/blocks/matchers.cpp index 882ae94..593c655 100644 --- a/src/blocks/matchers.cpp +++ b/src/blocks/matchers.cpp @@ -53,11 +53,19 @@ bool check_match(std::shared_ptr p, block::Ptr node, std::map(node) && !isa<::block::var_expr>(node)) return false; + if (p->var_name != "") { + var::Ptr v; + if (isa<::block::var>(node)) + v = to<::block::var>(node); + else + v = to<::block::var_expr>(node)->var1; + if (v->var_name != p->var_name) return false; + } break; case pattern::node_type::var_expr: - if (!isa<::block::var>(node)) return false; + if (!isa<::block::var_expr>(node)) return false; if (p->children.size() > 0) { - block::Ptr child = to<::block::var_expr>(node); + block::Ptr child = to<::block::var_expr>(node)->var1; if (!check_match(p->children[0], child, captures)) return false; } @@ -187,7 +195,17 @@ bool check_match(std::shared_ptr p, block::Ptr node, std::map(node)) return false; - // For now we will only check if it is a function call + if (p->children.size() > 0) { + auto fc = to<::block::function_call_expr>(node); + // THere should be an extra expression for the function itself + if (p->children.size() != fc->args.size() + 1) return false; + + block::Ptr child1 = fc->expr1; + if (!check_match(p->children[0], child1, captures)) return false; + for (unsigned i = 0; i < fc->args.size(); i++) { + if (!check_match(p->children[i+1], fc->args[i], captures)) return false; + } + } break; case pattern::node_type::initializer_list_expr: if (!isa<::block::initializer_list_expr>(node)) return false; diff --git a/src/blocks/replacers.cpp b/src/blocks/replacers.cpp index f46d0cc..dbc545f 100644 --- a/src/blocks/replacers.cpp +++ b/src/blocks/replacers.cpp @@ -178,7 +178,15 @@ block::Ptr create_ast(pattern::Ptr p, const std::map& m } return matches.at(p->name); case pattern::node_type::function_call_expr: - REPLACER_ASSERT(p->name != "", "Function call replacer currently only supports replacing with a reference to a capture"); + REPLACER_ASSERT(p->children.size() > 0 || p->name != "", "Function call must have atleast one child or must reference a capture"); + if (p->children.size() > 0) { + auto fc = std::make_shared<::block::function_call_expr>(); + fc->expr1 = create_expr_ast(p->children[0], matches); + for (unsigned i = 1; i < p->children.size(); i++) { + fc->args.push_back(create_expr_ast(p->children[i], matches)); + } + return fc; + } return matches.at(p->name); case pattern::node_type::initializer_list_expr: REPLACER_ASSERT(p->name != "", "Init list expr replacer currently only supports replacing with a reference to a capture"); @@ -189,7 +197,12 @@ block::Ptr create_ast(pattern::Ptr p, const std::map& m case pattern::node_type::addr_of_expr: return create_unary_ast<::block::addr_of_expr>(p, matches); case pattern::node_type::var: - REPLACER_ASSERT(p->name != "", "Var replacer must reference a capture"); + REPLACER_ASSERT(p->name != "" || p->var_name != "", "Var replacer must reference a capture or have a var name"); + if (p->var_name != "") { + ::block::var::Ptr t = std::make_shared<::block::var>(); + t->var_name = p->var_name; + return t; + } return matches.at(p->name); default: REPLACER_ASSERT(false, "This replacer is currently not supported");