Expression pattern matching
To find and replace an expression pattern, create a struct that inherits
publicly from bronto::rewrite_expr (either directly or indirectly) and use the
BRONTO_BEFORE() and BRONTO_AFTER() annotations to identify expressions and
define their replacements.
struct StringIsEmpty : bronto::rewrite_expr {
BRONTO_BEFORE()
bool equals_empty(std::string s) {
return s == "";
}
BRONTO_AFTER()
bool empty_method(std::string s) {
return s.empty();
}
};Example use cases
BRONTO_BEFORE
Requirements
Each struct inheriting from bronto::rewrite_expr must have one member function
or template member function marked BRONTO_BEFORE(). This function must have a
single return statement (and no other statements).
Semantics
The returned expression from a function annotated with BRONTO_BEFORE() defines
the pattern to be matched. The pattern is syntactic in the sense that any
implicit casts/conversions are ignored. However there are some syntactic
constructs that are also ignored. In particular, parentheses that do not change
the meaning of an expression are ignored in the pattern. For example, a pattern
such as (a + b) + c will match 1 + 2 + 3, even though it does not have
parentheses.
Parameters
Each function parameter represents a "hole" that can bind to any expression of the appropriate type ignoring qualifiers. If the parameter's type is dependent on a template parameter, the parameter represents any expression whose type can be represented by appropriate choices for the template parameters. In other words,
template <typename T>
BRONTO_BEFORE()
auto f(T *ptr) {
return ptr->something();
}will match calls to something through operator-> on a pointer type but will
not match calls to something on a std::unique_ptr. Even though
operator-> is defined, std::unique_ptr<U> will not bind to a function
template parameter T*.
For each matched pattern, the expressions and types that correspond to a
parameter and template parameter "holes" are said to be captured (the same
terminology as regular expression captures). These expressions and types can be
used in the replacement pattern annotated with BRONTO_AFTER.
BRONTO_AFTER
Requirements
Each struct inheriting from bronto::rewrite_expr must have one member function
or template member function marked BRONTO_AFTER(). The function must have a
single return statement and must be able to accept any function parameters or
template parameters from any function marked BRONTO_BEFORE() in the struct.
Semantics
The returned expression represents the pattern to replace things found by
BRONTO_BEFORE with. Each captured expression or type is used in place of the
parameter or template parameter of the same name.