Callbacks must be functions that take three arguments: The expression to rewrite, the environment of the function we are rewriting (i.e. the environment it is defined in, not the function call frame), and a list of formal parameters of the function we are translating.
rewrite_callbacks() analysis_callbacks() with_atomic_callback(callbacks, fn) with_pairlist_callback(callbacks, fn) with_symbol_callback(callbacks, fn, include_missing = FALSE) with_primitive_callback(callbacks, fn) with_call_callback(callbacks, fn) with_topdown_pairlist_callback(callbacks, fn) with_topdown_call_callback(callbacks, fn)
callbacks | The list of callbacks |
---|---|
fn | A function to install as a callback. |
include_missing | For symbols, it is possible that the expression is
missing. This can happen in pair-lists if a function parameter does not
have a default argument. By default, the callback is not invoked on missing
expressions--there is very little you can do with them -- but you can
include them by setting this parameter to |
The flow of a depth-first traversal is as follows:
For expressions that are atomic, i.e. are either atomic values, pairlists,
symbols, or primitives, the corresponding callback is called with the
expression. The callbacks are called with the expression, expr
, the
environment of the function we are traversing, env
, the parameters of that
function, params
, information collected top-down in topdown
, warning
flags through the wflags
parameter, and any additional user-provided
arguments through ...
. If the callbacks are used in a rewrite traversal,
see depth_first_rewrite_function()
, they must return an expression. This
expression will be inserted as a substitute of the expr
argument in the
function being rewritten. If the callback is part of an analysis, see
depth_first_analyse_function()
, then it can return any data; what it
returns will be provided to the callbacks on the enclosing expression via the
bottomup
parameter.
For call
expressions, the topdown
callback is invoked before the call is
traversed. It is provided with the same arguments as the other callbacks and
in addition a thunk skip
that it can use to prevent the depth-first
traversal to explore the call further. Whatever the topdown
callback
returns will be provided to the call callback via the argument topdown
it
it is called (i.e. if the topdown
callback doesn't invoke skip
).
After the topdown
callback is executed, if it doesn't call skip
, the
call
callback is called on the expression. It is called with the same
arguments as the other callbacks, and must return an expression if part of a
rewrite traversal or any collected information if part of an analysis
traversal.
rewrite_callbacks
: Default callbacks for rewriting expressions
analysis_callbacks
: Default callbacks for analysing expressions
with_atomic_callback
: Set the atomic callback function.
with_pairlist_callback
: Set the pairlist callback function.
with_symbol_callback
: Set the symbol callback function.
with_primitive_callback
: Set the primitive callback function.
with_call_callback
: Set the call callback function.
with_topdown_pairlist_callback
: Set the topdown information-passing callback
function for pair-lists
with_topdown_call_callback
: Set the topdown information-passing callback
function for calls.
with_atomic_callback
with_symbol_callback
with_primitive_callback
with_pairlist_callback
with_call_callback
with_topdown_pairlist_callback
with_topdown_call_callback
warning_flags
f <- function(x) 2 + x cb <- rewrite_callbacks() %>% add_call_callback(f, function(expr, ...) { quote(2 + x) }) tr_f <- . %>% rewrite() %>% rewrite_with(cb) g <- function(y) y + f(y) tr_f(g)#> function (y) #> y + (2 + x) #> <environment: 0x11465c840>collect_symbols <- function(expr, ...) { list(symbols = as.character(expr)) } callbacks <- analysis_callbacks() %>% with_symbol_callback(collect_symbols) f %>% analyse() %>% analyse_with(callbacks)#> $symbols #> [1] "+" "x" #>