Skip to main content

CALLER_CALL_HELPER

Constant CALLER_CALL_HELPER 

Source
const CALLER_CALL_HELPER: &str = r#"# Internal helper: the call a wrapper with a `.call` formal attributes its
# conditions to, as written. A `#[miniextendr(noexport, call = caller)]`
# wrapper calls it as its first statement, `.mx_call <- .miniextendr_caller_call(.call)`,
# with its trailing `.call = NULL` formal (an S3 method has none and calls it
# without an argument). A `#[miniextendr(call_arg)]` wrapper binds
# `.mx_call <- if (is.null(.call)) sys.call() else .miniextendr_caller_call(.call, own = TRUE)`,
# so it calls the helper only for a `.call` that isn't NULL. The calling chain
# is [caller's caller] <- [caller] <- [wrapper] <- [this helper]:
# `sys.parent(1L)` is the wrapper's frame, `sys.parent(2L)` its caller's.
# `call` is what the wrapper's caller passed as `.call`:
# - an environment: a hand-written helper between the public function and the
#   wrapper passes its caller's frame (`call = parent.frame()` in the helper's
#   formals), or a function composing the wrapper its own (`environment()`).
#   The result is the call of the closure owning that frame.
#   `match(TRUE, ...)` takes the oldest frame with that environment, the
#   closure's own, ahead of a later `eval()` over it. An environment that is no
#   closure's live frame (`globalenv()`) counts as NULL.
# - a call object: used as is.
# - NULL, the default: under `own = TRUE`, the wrapper's own call, without
#   `.call`. Otherwise, when the wrapper's caller is a closure, that caller's
#   call; else (top level, or an `eval()` frame such as a testthat block,
#   `source()` or `local()`, whose frame function is not a closure and whose
#   call names `eval`) the wrapper's own call, without `.call`.
# - anything else: an argument error on `.call` against the wrapper's own call,
#   which also catches a positional argument too many.
.miniextendr_caller_call <- function(call = NULL, own = FALSE) {
  wrapper <- sys.parent(1L)
  if (is.environment(call)) {
    frames <- sys.frames()
    i <- match(TRUE, vapply(frames, identical, NA, call))
    if (!is.na(i) && typeof(sys.function(i)) == "closure") return(sys.call(i))
  } else if (is.call(call)) {
    return(call)
  } else if (!is.null(call)) {
    .miniextendr_arg_error(".call", "must be NULL, an environment or a call", sys.call(wrapper))
  }
  if (!own) {
    parent <- sys.parent(2L)
    if (parent > 0L && typeof(sys.function(parent)) == "closure") return(sys.call(parent))
  }
  call <- sys.call(wrapper)
  call$.call <- NULL
  call
}
"#;
Expand description

R source of the .miniextendr_caller_call helper, with its comment block, as written into the wrappers preamble by write_r_wrappers_to_file: the call a call = caller wrapper reports (#1450, #1548, #1552), including the frame or call a hand-written helper passed as the wrapper’s .call formal (#1613), and the frame or call a call_arg wrapper was passed (own = TRUE, #1834).