1
2#  Soft-deprecated in rlang 0.4.0
3
4##  Types
5
6#' Base type of an object
7#'
8#' @description
9#'
10#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("soft-deprecated")}
11#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("experimental")}
12#'
13#' This is equivalent to [base::typeof()] with a few differences that
14#' make dispatching easier:
15#' * The type of one-sided formulas is "quote".
16#' * The type of character vectors of length 1 is "string".
17#' * The type of special and builtin functions is "primitive".
18#'
19#'
20#' @section Life cycle:
21#'
22#' `type_of()` is an experimental function. Expect API changes.
23#'
24#' @param x An R object.
25#' @export
26#' @keywords internal
27#' @examples
28#' type_of(10L)
29#'
30#' # Quosures are treated as a new base type but not formulas:
31#' type_of(quo(10L))
32#' type_of(~10L)
33#'
34#' # Compare to base::typeof():
35#' typeof(quo(10L))
36#'
37#' # Strings are treated as a new base type:
38#' type_of(letters)
39#' type_of(letters[[1]])
40#'
41#' # This is a bit inconsistent with the core language tenet that data
42#' # types are vectors. However, treating strings as a different
43#' # scalar type is quite helpful for switching on function inputs
44#' # since so many arguments expect strings:
45#' switch_type("foo", character = abort("vector!"), string = "result")
46#'
47#' # Special and builtin primitives are both treated as primitives.
48#' # That's because it is often irrelevant which type of primitive an
49#' # input is:
50#' typeof(list)
51#' typeof(`$`)
52#' type_of(list)
53#' type_of(`$`)
54type_of <- function(x) {
55  signal_soft_deprecated(c(
56    "`type_of()` is deprecated as of rlang 0.4.0.",
57    "Please use `typeof()` or your own version instead."
58  ))
59  type_of_(x)
60}
61
62#' Dispatch on base types
63#'
64#' @description
65#'
66#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("soft-deprecated")}
67#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("experimental")}
68#'
69#' `switch_type()` is equivalent to
70#' \code{\link[base]{switch}(\link{type_of}(x, ...))}, while
71#' `switch_class()` switchpatches based on `class(x)`. The `coerce_`
72#' versions are intended for type conversion and provide a standard
73#' error message when conversion fails.
74#'
75#'
76#' @param .x An object from which to dispatch.
77#' @param ... Named clauses. The names should be types as returned by
78#'   [type_of()].
79#' @param .to This is useful when you switchpatch within a coercing
80#'   function. If supplied, this should be a string indicating the
81#'   target type. A catch-all clause is then added to signal an error
82#'   stating the conversion failure. This type is prettified unless
83#'   `.to` inherits from the S3 class `"AsIs"` (see [base::I()]).
84#' @export
85#' @keywords internal
86#' @examples
87#' switch_type(3L,
88#'   double = "foo",
89#'   integer = "bar",
90#'   "default"
91#' )
92#'
93#' # Use the coerce_ version to get standardised error handling when no
94#' # type matches:
95#' to_chr <- function(x) {
96#'   coerce_type(x, "a chr",
97#'     integer = as.character(x),
98#'     double = as.character(x)
99#'   )
100#' }
101#' to_chr(3L)
102#'
103#' # Strings have their own type:
104#' switch_type("str",
105#'   character = "foo",
106#'   string = "bar",
107#'   "default"
108#' )
109#'
110#' # Use a fallthrough clause if you need to dispatch on all character
111#' # vectors, including strings:
112#' switch_type("str",
113#'   string = ,
114#'   character = "foo",
115#'   "default"
116#' )
117#'
118#' # special and builtin functions are treated as primitive, since
119#' # there is usually no reason to treat them differently:
120#' switch_type(base::list,
121#'   primitive = "foo",
122#'   "default"
123#' )
124#' switch_type(base::`$`,
125#'   primitive = "foo",
126#'   "default"
127#' )
128#'
129#' # closures are not primitives:
130#' switch_type(rlang::switch_type,
131#'   primitive = "foo",
132#'   "default"
133#' )
134switch_type <- function(.x, ...) {
135  signal_soft_deprecated(c(
136    "`switch_type()` is soft-deprecated as of rlang 0.4.0.",
137    "Please use `switch(typeof())` or `switch(my_typeof())` instead."
138  ))
139  switch(type_of_(.x), ...)
140}
141#' @rdname switch_type
142#' @export
143coerce_type <- function(.x, .to, ...) {
144  signal_soft_deprecated("`coerce_type()` is soft-deprecated as of rlang 0.4.0.")
145  switch(type_of_(.x), ..., abort_coercion(.x, .to))
146}
147#' @rdname switch_type
148#' @export
149switch_class <- function(.x, ...) {
150  signal_soft_deprecated("`switch_class()` is soft-deprecated as of rlang 0.4.0.")
151  switch(class(.x), ...)
152}
153#' @rdname switch_type
154#' @export
155coerce_class <- function(.x, .to, ...) {
156  signal_soft_deprecated("`coerce_class()` is soft-deprecated as of rlang 0.4.0.")
157  switch(class(.x), ..., abort_coercion(.x, .to))
158}
159
160
161##  Casting
162
163#' Coerce an object to a base type
164#'
165#' @description
166#'
167#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("soft-deprecated")}
168#'
169#' These are equivalent to the base functions (e.g. [as.logical()],
170#' [as.list()], etc), but perform coercion rather than conversion.
171#' This means they are not generic and will not call S3 conversion
172#' methods. They only attempt to coerce the base type of their
173#' input. In addition, they have stricter implicit coercion rules and
174#' will never attempt any kind of parsing. E.g. they will not try to
175#' figure out if a character vector represents integers or booleans.
176#' Finally, they treat attributes consistently, unlike the base R
177#' functions: all attributes except names are removed.
178#'
179#'
180#' @section Lifecycle:
181#'
182#' These functions are deprecated in favour of `vctrs::vec_cast()`.
183#'
184#'
185#' @section Coercion to logical and numeric atomic vectors:
186#'
187#' * To logical vectors: Integer and integerish double vectors. See
188#'   [is_integerish()].
189#' * To integer vectors: Logical and integerish double vectors.
190#' * To double vectors: Logical and integer vectors.
191#' * To complex vectors: Logical, integer and double vectors.
192#'
193#'
194#' @section Coercion to character vectors:
195#'
196#' `as_character()` and `as_string()` have an optional `encoding`
197#' argument to specify the encoding. R uses this information for
198#' internal handling of strings and character vectors. Note that this
199#' is only declarative, no encoding conversion is attempted.
200#'
201#' Note that only `as_string()` can coerce symbols to a scalar
202#' character vector. This makes the code more explicit and adds an
203#' extra type check.
204#'
205#'
206#' @section Coercion to lists:
207#'
208#' `as_list()` only coerces vector and dictionary types (environments
209#' are an example of dictionary type). Unlike [base::as.list()],
210#' `as_list()` removes all attributes except names.
211#'
212#'
213#' @section Effects of removing attributes:
214#'
215#' A technical side-effect of removing the attributes of the input is
216#' that the underlying objects has to be copied. This has no
217#' performance implications in the case of lists because this is a
218#' shallow copy: only the list structure is copied, not the contents
219#' (see [duplicate()]). However, be aware that atomic vectors
220#' containing large amounts of data will have to be copied.
221#'
222#' In general, any attribute modification creates a copy, which is why
223#' it is better to avoid using attributes with heavy atomic vectors.
224#' Uncopyable objects like environments and symbols are an exception
225#' to this rule: in this case, attributes modification happens in
226#' place and has side-effects.
227#'
228#' @inheritParams string
229#' @param x An object to coerce to a base type.
230#'
231#' @keywords internal
232#' @examples
233#' # Coercing atomic vectors removes attributes with both base R and rlang:
234#' x <- structure(TRUE, class = "foo", bar = "baz")
235#' as.logical(x)
236#'
237#' # But coercing lists preserves attributes in base R but not rlang:
238#' l <- structure(list(TRUE), class = "foo", bar = "baz")
239#' as.list(l)
240#' as_list(l)
241#'
242#' # Implicit conversions are performed in base R but not rlang:
243#' as.logical(l)
244#' \dontrun{
245#' as_logical(l)
246#' }
247#'
248#' # Conversion methods are bypassed, making the result of the
249#' # coercion more predictable:
250#' as.list.foo <- function(x) "wrong"
251#' as.list(l)
252#' as_list(l)
253#'
254#' # The input is never parsed. E.g. character vectors of numbers are
255#' # not converted to numeric types:
256#' as.integer("33")
257#' \dontrun{
258#' as_integer("33")
259#' }
260#'
261#'
262#' # With base R tools there is no way to convert an environment to a
263#' # list without either triggering method dispatch, or changing the
264#' # original environment. as_list() makes it easy:
265#' x <- structure(as_environment(mtcars[1:2]), class = "foobar")
266#' as.list.foobar <- function(x) abort("dont call me")
267#' as_list(x)
268#' @name vector-coercion
269NULL
270
271signal_deprecated_cast <- function(fn, env = caller_env(2)) {
272  signal_soft_deprecated(env = env, c(
273    sprintf("`%s()` is deprecated as of rlang 0.4.0", fn),
274    "Please use `vctrs::vec_cast()` instead."
275  ))
276}
277
278#' @rdname vector-coercion
279#' @export
280as_logical <- function(x) {
281  signal_deprecated_cast("as_logical")
282  coerce_type_vec(x, friendly_type("logical"),
283    logical = { attributes(x) <- NULL; x },
284    integer = as_base_type(x, as.logical),
285    double = as_integerish_type(x, as.logical, "logical")
286  )
287}
288#' @rdname vector-coercion
289#' @export
290as_integer <- function(x) {
291  signal_deprecated_cast("as_integer")
292  coerce_type_vec(x, friendly_type("integer"),
293    logical = as_base_type(x, as.integer),
294    integer = { attributes(x) <- NULL; x },
295    double = as_integerish_type(x, as.integer, "integer")
296  )
297}
298#' @rdname vector-coercion
299#' @export
300as_double <- function(x) {
301  signal_deprecated_cast("as_double")
302  coerce_type_vec(x, friendly_type("double"),
303    logical = ,
304    integer = as_base_type(x, as.double),
305    double = { attributes(x) <- NULL; x }
306  )
307}
308#' @rdname vector-coercion
309#' @export
310as_complex <- function(x) {
311  signal_deprecated_cast("as_complex")
312  coerce_type_vec(x, friendly_type("complex"),
313    logical = ,
314    integer = ,
315    double = as_base_type(x, as.complex),
316    complex = { attributes(x) <- NULL; x }
317  )
318}
319#' @rdname vector-coercion
320#' @export
321as_character <- function(x, encoding = NULL) {
322  signal_deprecated_cast("as_character")
323  if (is_unspecified(x)) {
324    return(rep_along(x, na_chr))
325  }
326  coerce_type_vec(x, friendly_type("character"),
327    string = ,
328    character = {
329      attributes(x) <- NULL
330      if (!is_null(encoding)) {
331        Encoding(x) <- encoding
332      }
333      x
334    }
335  )
336}
337#' @rdname vector-coercion
338#' @export
339as_list <- function(x) {
340  signal_deprecated_cast("as_list")
341  switch_type(x,
342    environment = env_as_list(x),
343    vec_as_list(x)
344  )
345}
346env_as_list <- function(x) {
347  names_x <- names(x)
348  x <- as_base_type(x, as.list)
349  set_names(x, .Call(rlang_unescape_character, names_x))
350}
351vec_as_list <- function(x) {
352  coerce_type_vec(x, friendly_type("list"),
353    logical = ,
354    integer = ,
355    double = ,
356    string = ,
357    character = ,
358    complex = ,
359    raw = as_base_type(x, as.list),
360    list = { attributes(x) <- NULL; x }
361  )
362}
363
364is_unspecified <- function(x) {
365  is_logical(x) && all(map_lgl(x, identical, NA))
366}
367
368as_base_type <- function(x, as_type) {
369  # Zap attributes temporarily instead of unclassing. We want to avoid
370  # method dispatch, but we also want to avoid an extra copy of atomic
371  # vectors: the first when unclassing, the second when coercing. This
372  # is also useful for uncopyable types like environments.
373  attrs <- .Call(rlang_attrib, x)
374  .Call(rlang_poke_attrib, x, NULL)
375
376  # This function assumes that the target type is different than the
377  # input type, otherwise no duplication is done and the output will
378  # be modified by side effect when we restore the input attributes.
379  on.exit(.Call(rlang_poke_attrib, x, attrs))
380
381  as_type(x)
382}
383as_integerish_type <- function(x, as_type, to) {
384  if (is_integerish(x)) {
385    as_base_type(x, as_type)
386  } else {
387    abort(paste0(
388      "Can't convert a fractional double vector to ", friendly_type(to), ""
389    ))
390  }
391}
392
393coerce_type_vec <- function(.x, .to, ...) {
394  # Cannot reuse coerce_type() because switch() has a bug with
395  # fallthrough and multiple levels of dots forwarding.
396  out <- switch(type_of_(.x), ..., abort_coercion(.x, .to))
397
398  if (!is_null(names(.x))) {
399    # Avoid a copy of `out` when we restore the names, since it could be
400    # a heavy atomic vector. We own `out`, so it is ok to change its
401    # attributes inplace.
402    .Call(rlang_poke_attrib, out, pairlist(names = names(.x)))
403  }
404
405  out
406}
407vec_coerce <- function(x, type) {
408  .Call(rlang_vec_coerce, x, type)
409}
410
411
412#  Stack and frames  -------------------------------------------------
413
414#' Get caller frame
415#'
416#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
417#'
418#' @param n Number of frames to go back.
419#' @keywords internal
420#' @export
421caller_frame <- function(n = 1) {
422  warn_deprecated("`caller_frame()` is deprecated as of rlang 0.3.0.")
423  call_frame(n + 2)
424}
425
426#' Call stack information
427#'
428#' @description
429#'
430#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
431#'
432#' The `eval_` and `call_` families of functions provide a replacement
433#' for the base R functions prefixed with `sys.` (which are all about
434#' the context stack), as well as for [parent.frame()] (which is the
435#' only base R function for querying the call stack). The context
436#' stack includes all R-level evaluation contexts. It is linear in
437#' terms of execution history but due to lazy evaluation it is
438#' potentially nonlinear in terms of call history. The call stack
439#' history, on the other hand, is homogenous.
440#'
441#' @details
442#'
443#' `ctxt_frame()` and `call_frame()` return a `frame` object
444#' containing the following fields: `expr` and `env` (call expression
445#' and evaluation environment), `pos` and `caller_pos` (position of
446#' current frame in the context stack and position of the caller), and
447#' `fun` (function of the current frame). `ctxt_stack()` and
448#' `call_stack()` return a list of all context or call frames on the
449#' stack. Finally, `ctxt_depth()` and `call_depth()` report the
450#' current context position or the number of calling frames on the
451#' stack.
452#'
453#' The base R functions take two sorts of arguments to indicate which
454#' frame to query: `which` and `n`. The `n` argument is
455#' straightforward: it's the number of frames to go down the stack,
456#' with `n = 1` referring to the current context. The `which` argument
457#' is more complicated and changes meaning for values lower than 1.
458#' For the sake of consistency, the rlang functions all take the
459#' same kind of argument `n`. This argument has a single meaning (the
460#' number of frames to go down the stack) and cannot be lower than 1.
461#'
462#' Note finally that `parent.frame(1)` corresponds to
463#' `call_frame(2)$env`, as `n = 1` always refers to the current
464#' frame. This makes the `_frame()` and `_stack()` functions
465#' consistent: `ctxt_frame(2)` is the same as `ctxt_stack()[[2]]`.
466#' Also, `ctxt_depth()` returns one more frame than
467#' [base::sys.nframe()] because it counts the global frame. That is
468#' consistent with the `_stack()` functions which return the global
469#' frame as well. This way, `call_stack(call_depth())` is the same as
470#' `global_frame()`.
471#'
472#'
473#' @section Life cycle:
474#'
475#' These functions are soft-deprecated and replaced by [trace_back()].
476#'
477#' @param n The number of frames to go back in the stack.
478#' @param clean Whether to post-process the call stack to clean
479#'   non-standard frames. If `TRUE`, suboptimal call-stack entries by
480#'   [base::eval()] will be cleaned up: the duplicate frame created by
481#'   `eval()` is eliminated.
482#' @param trim The number of layers of intervening frames to trim off
483#'   the stack. See [stack_trim()] and examples.
484#' @name stack
485#' @keywords internal
486#' @examples
487#' # Expressions within arguments count as contexts
488#' identity(identity(ctxt_depth())) # returns 2
489#'
490#' # But they are not part of the call stack because arguments are
491#' # evaluated within the calling function (or the global environment
492#' # if called at top level)
493#' identity(identity(call_depth())) # returns 0
494#'
495#' # The context stacks includes all intervening execution frames. The
496#' # call stack doesn't:
497#' f <- function(x) identity(x)
498#' f(f(ctxt_stack()))
499#' f(f(call_stack()))
500#'
501#' g <- function(cmd) cmd()
502#' f(g(ctxt_stack))
503#' f(g(call_stack))
504#'
505#' # The rlang _stack() functions return a list of frame
506#' # objects. Use purrr::transpose() or index a field with
507#' # purrr::map()'s to extract a particular field from a stack:
508#'
509#' # stack <- f(f(call_stack()))
510#' # purrr::map(stack, "env")
511#' # purrr::transpose(stack)$expr
512#'
513#' # current_frame() is an alias for ctxt_frame(1)
514#' fn <- function() list(current = current_frame(), first = ctxt_frame(1))
515#' fn()
516#'
517#' # While current_frame() is the top of the stack, global_frame() is
518#' # the bottom:
519#' fn <- function() {
520#'   n <- ctxt_depth()
521#'   ctxt_frame(n)
522#' }
523#' identical(fn(), global_frame())
524#'
525#'
526#' # ctxt_stack() returns a stack with all intervening frames. You can
527#' # trim layers of intervening frames with the trim argument:
528#' identity(identity(ctxt_stack()))
529#' identity(identity(ctxt_stack(trim = 1)))
530#'
531#' # ctxt_stack() is called within fn() with intervening frames:
532#' fn <- function(trim) identity(identity(ctxt_stack(trim = trim)))
533#' fn(0)
534#'
535#' # We can trim the first layer of those:
536#' fn(1)
537#'
538#' # The outside intervening frames (at the fn() call site) are still
539#' # returned, but can be trimmed as well:
540#' identity(identity(fn(1)))
541#' identity(identity(fn(2)))
542#'
543#' g <- function(trim) identity(identity(fn(trim)))
544#' g(2)
545#' g(3)
546NULL
547
548new_frame <- function(x) {
549  structure(x, class = "frame")
550}
551#' @export
552print.frame <- function(x, ...) {
553  cat("<frame ", x$pos, ">", sep = "")
554  if (!x$pos) {
555    cat(" [global]\n")
556  } else {
557    cat(" (", x$caller_pos, ")\n", sep = "")
558  }
559
560  expr <- deparse(x$expr)
561  if (length(expr) > 1) {
562    expr <- paste(expr[[1]], "<...>")
563  }
564  cat("expr: ", expr, "\n", sep = "")
565  cat("env:  [", env_format(x$env), "]\n", sep = "")
566}
567#' Is object a frame?
568#'
569#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
570#'
571#' @param x Object to test
572#' @keywords internal
573#' @export
574is_frame <- function(x) {
575  inherits(x, "frame")
576}
577
578#' @rdname stack
579#' @export
580global_frame <- function() {
581  warn_deprecated("`global_frame()` is deprecated as of rlang 0.3.0.")
582  new_frame(list(
583    pos = 0L,
584    caller_pos = NA_integer_,
585    expr = NULL,
586    env = globalenv(),
587    fn = NULL,
588    fn_name = NULL
589  ))
590}
591#' @rdname stack
592#' @export
593current_frame <- function() {
594  warn_deprecated("`current_frame()` is deprecated as of rlang 0.3.0.")
595  ctxt_frame(2)
596}
597
598#' @rdname stack
599#' @export
600ctxt_frame <- function(n = 1) {
601  warn_deprecated("`ctxt_frame()` is deprecated as of rlang 0.3.0.")
602  stopifnot(n > 0)
603  pos <- sys.nframe() - n
604
605  if (pos < 0L) {
606    stop("not that many frames on the stack", call. = FALSE)
607  } else if (pos == 0L) {
608    global_frame()
609  } else {
610    new_frame(list(
611      pos = pos,
612      caller_pos = sys.parent(n + 1),
613      expr = sys.call(-n),
614      env = sys.frame(-n),
615      fn = sys.function(-n),
616      fn_name = call_name(sys.call(-n))
617    ))
618  }
619}
620
621# Positions of frames in the call stack up to `n`
622trail_make <- function(callers, n = NULL, clean = TRUE) {
623  n_ctxt <- length(callers)
624  if (is.null(n)) {
625    n_max <- n_ctxt
626  } else {
627    if (n > n_ctxt) {
628      stop("not that many frames on the evaluation stack", call. = FALSE)
629    }
630    n_max <- n + 1
631  }
632
633  state <- trail_next(callers, 1, clean)
634  if (!length(state$i) || state$i == 0) {
635    return(0L)
636  }
637  j <- 1
638
639  # Preallocate a sufficiently large vector
640  out <- integer(n_max)
641  out[j] <- state$i
642
643  while (state$i != 0 && j < n_max) {
644    j <- j + 1
645    n_ctxt <- length(state$callers)
646    next_pos <- n_ctxt - state$i + 1
647    state <- trail_next(state$callers, next_pos, clean)
648    out[j] <- state$i
649  }
650
651  # Return relevant subset
652  if (!is.null(n) && n > j) {
653    stop("not that many frames on the call stack", call. = FALSE)
654  }
655  out[seq_len(j)]
656}
657
658trail_next <- function(callers, i, clean) {
659  if (i == 0L) {
660    return(list(callers = callers, i = 0L))
661  }
662
663  i <- callers[i]
664
665  if (clean) {
666    # base::Recall() creates a custom context with the wrong sys.parent()
667    if (identical(sys.function(i - 1L), base::Recall)) {
668      i_pos <- trail_index(callers, i)
669      callers[i_pos] <- i - 1L
670    }
671
672    # The R-level eval() creates two contexts. We skip the second one
673    if (length(i) && is_prim_eval(sys.function(i))) {
674      n_ctxt <- length(callers)
675      special_eval_pos <- trail_index(callers, i)
676      callers <- callers[-special_eval_pos]
677      i <- i - 1L
678    }
679
680  }
681
682  list(callers = callers, i = i)
683}
684
685trail_index <- function(callers, i) {
686  n_ctxt <- length(callers)
687  n_ctxt - i + 1L
688}
689
690#' @rdname stack
691#' @export
692call_frame <- function(n = 1, clean = TRUE) {
693  stopifnot(n > 0)
694
695  eval_callers <- ctxt_stack_callers()
696  trail <- trail_make(eval_callers, n, clean = clean)
697  pos <- trail[n]
698
699  if (identical(pos, 0L)) {
700    return(global_frame())
701  }
702
703  frame <- new_frame(list(
704    pos = pos,
705    caller_pos = trail[n + 1],
706    expr = sys.call(pos),
707    env = sys.frame(pos),
708    fn = sys.function(pos),
709    fn_name = call_name(sys.call(pos))
710  ))
711
712  if (clean) {
713    frame <- frame_clean_eval(frame)
714  }
715  frame
716}
717
718
719# The _depth() functions count the global frame as well
720
721#' @rdname stack
722#' @export
723ctxt_depth <- function() {
724  warn_deprecated("`ctxt_depth()` is deprecated as of rlang 0.3.0.")
725  sys.nframe()
726}
727#' @rdname stack
728#' @export
729call_depth <- function() {
730  warn_deprecated("`call_depth()` is deprecated as of rlang 0.3.0.")
731  eval_callers <- ctxt_stack_callers()
732  trail <- trail_make(eval_callers)
733  length(trail)
734}
735
736
737# Summaries ----------------------------------------------------------
738
739#' @rdname stack
740#' @export
741ctxt_stack <- function(n = NULL, trim = 0) {
742  warn_deprecated("`ctxt_stack()` is deprecated as of rlang 0.3.0.")
743
744  stack_data <- list(
745    pos = ctxt_stack_trail(),
746    caller_pos = ctxt_stack_callers(),
747    expr = ctxt_stack_exprs(),
748    env = ctxt_stack_envs(),
749    fn = ctxt_stack_fns()
750  )
751
752  # Remove ctxt_stack() from stack
753  stack_data <- map(stack_data, drop_first)
754
755  stack_data <- stack_subset(stack_data, n)
756  stack_data$fn_name <- map(stack_data$expr, call_name)
757
758  stack <- transpose(stack_data)
759  stack <- map(stack, new_frame)
760
761  if (is.null(n) || (length(n) && n > length(stack))) {
762    stack <- c(stack, list(global_frame()))
763  }
764  if (trim > 0) {
765    stack <- stack_trim(stack, n = trim + 1)
766  }
767
768  structure(stack, class = c("ctxt_stack", "stack"))
769}
770
771ctxt_stack_trail <- function() {
772  pos <- sys.nframe() - 1
773  seq(pos, 1)
774}
775ctxt_stack_exprs <- function() {
776  exprs <- sys.calls()
777  rev(drop_last(exprs))
778}
779ctxt_stack_envs <- function(n = 1) {
780  envs <- sys.frames()
781  rev(drop_last(envs))
782}
783ctxt_stack_callers <- function() {
784  callers <- sys.parents()
785  rev(drop_last(callers))
786}
787ctxt_stack_fns <- function() {
788  pos <- sys.nframe() - 1
789  map(seq(pos, 1), sys.function)
790}
791
792stack_subset <- function(stack_data, n) {
793  if (length(n)) {
794    stopifnot(n > 0)
795    n_stack <- length(stack_data[[1]])
796    if (n == n_stack + 1) {
797      # We'll add the global frame later
798      n <- n <- n - 1
799    } else if (n > n_stack + 1) {
800      stop("not that many frames on the stack", call. = FALSE)
801    }
802    stack_data <- map(stack_data, `[`, seq_len(n))
803  }
804  stack_data
805}
806
807#' @rdname stack
808#' @export
809call_stack <- function(n = NULL, clean = TRUE) {
810  warn_deprecated("`call_stack()` is deprecated as of rlang 0.3.0.")
811
812  eval_callers <- ctxt_stack_callers()
813  trail <- trail_make(eval_callers, n, clean = clean)
814
815  stack_data <- list(
816    pos = drop_last(trail),
817    caller_pos = drop_first(trail),
818    expr = map(trail, sys.call),
819    env = map(trail, sys.frame),
820    fn = map(trail, sys.function)
821  )
822  stack_data$fn_name <- map(stack_data$expr, call_name)
823
824  stack <- transpose(stack_data)
825  stack <- map(stack, new_frame)
826  if (clean) {
827    stack <- map(stack, frame_clean_eval)
828  }
829
830  if (trail[length(trail)] == 0L) {
831    stack <- c(stack, list(global_frame()))
832  }
833
834  structure(stack, class = c("call_stack", "stack"))
835}
836
837frame_clean_eval <- function(frame) {
838  if (identical(frame$fn, base::eval)) {
839    # Use the environment from the context created in do_eval()
840    # (the context with the fake primitive call)
841    stopifnot(is_prim_eval(sys.function(frame$pos + 1)))
842    frame$env <- sys.frame(frame$pos + 1)
843  }
844
845  frame
846}
847
848#' Is object a stack?
849#'
850#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("soft-deprecated")}
851#'
852#' @param x An object to test
853#' @keywords internal
854#' @export
855is_stack <- function(x) {
856  warn_deprecated("`is_stack()` is deprecated as of rlang 0.3.0.")
857  inherits(x, "stack")
858}
859
860#' @rdname is_stack
861#' @export
862is_eval_stack <- function(x) {
863  warn_deprecated("`is_eval_stack()` is deprecated as of rlang 0.3.0.")
864  inherits(x, "ctxt_stack")
865}
866
867#' @rdname is_stack
868#' @export
869is_call_stack <- function(x) {
870  warn_deprecated("`is_call_stack()` is deprecated as of rlang 0.3.0.")
871  inherits(x, "call_stack")
872}
873
874#' @export
875`[.stack` <- function(x, i) {
876  structure(NextMethod(), class = class(x))
877}
878
879# Handles global_frame() whose `caller_pos` is NA
880sys_frame <- function(n) {
881  if (is.na(n)) {
882    NULL
883  } else {
884    sys.frame(n)
885  }
886}
887
888#' Find the position or distance of a frame on the evaluation stack
889#'
890#' @description
891#'
892#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
893#'
894#' The frame position on the stack can be computed by counting frames
895#' from the global frame (the bottom of the stack, the default) or
896#' from the current frame (the top of the stack).
897#'
898#' @details
899#'
900#' While this function returns the position of the frame on the
901#' evaluation stack, it can safely be called with intervening frames
902#' as those will be discarded.
903#'
904#'
905#' @section Life cycle:
906#'
907#' These functions are deprecated and replaced by [trace_back()].
908#'
909#' @param frame The environment of a frame. Can be any object with a
910#'   [get_env()] method. Note that for frame objects, the position from
911#'   the global frame is simply `frame$pos`. Alternatively, `frame`
912#'   can be an integer that represents the position on the stack (and
913#'   is thus returned as is if `from` is "global".
914#' @param from Whether to compute distance from the global frame (the
915#'   bottom of the evaluation stack), or from the current frame (the
916#'   top of the evaluation stack).
917#'
918#' @keywords internal
919#' @export
920#' @examples
921#' fn <- function() g(environment())
922#' g <- function(env) frame_position(env)
923#'
924#' # frame_position() returns the position of the frame on the evaluation stack:
925#' fn()
926#' identity(identity(fn()))
927#'
928#' # Note that it trims off intervening calls before counting so you
929#' # can safely nest it within other calls:
930#' g <- function(env) identity(identity(frame_position(env)))
931#' fn()
932#'
933#' # You can also ask for the position from the current frame rather
934#' # than the global frame:
935#' fn <- function() g(environment())
936#' g <- function(env) h(env)
937#' h <- function(env) frame_position(env, from = "current")
938#' fn()
939frame_position <- function(frame, from = c("global", "current")) {
940  warn_deprecated("`frame_position()` is deprecated as of rlang 0.3.0.")
941
942  stack <- stack_trim(ctxt_stack(), n = 2)
943
944  if (arg_match(from) == "global") {
945    frame_position_global(frame, stack)
946  } else {
947    caller_pos <- call_frame(2)$pos
948    frame_position_current(frame, stack, caller_pos)
949  }
950}
951
952frame_position_global <- function(frame, stack = NULL) {
953  if (is_frame(frame)) {
954    return(frame$pos)
955  } else if (is_integerish(frame)) {
956    return(frame)
957  }
958
959  frame <- get_env(frame)
960  stack <- stack %||% stack_trim(ctxt_stack(), n = 2)
961  envs <- pluck(stack, "env")
962
963  i <- 1
964  for (env in envs) {
965    if (identical(env, frame)) {
966      return(length(envs) - i)
967    }
968    i <- i + 1
969  }
970
971  abort("`frame` not found on evaluation stack")
972}
973
974frame_position_current <- function(frame, stack = NULL,
975                                   caller_pos = NULL) {
976  if (is_integerish(frame)) {
977    pos <- frame
978  } else {
979    stack <- stack %||% stack_trim(ctxt_stack(), n = 2)
980    pos <- frame_position_global(frame, stack)
981  }
982  caller_pos <- caller_pos %||% call_frame(2)$pos
983  caller_pos - pos + 1
984}
985
986
987#' Trim top call layers from the evaluation stack
988#'
989#' @description
990#'
991#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
992#'
993#' [ctxt_stack()] can be tricky to use in real code because all
994#' intervening frames are returned with the stack, including those at
995#' `ctxt_stack()` own call site. `stack_trim()` makes it easy to
996#' remove layers of intervening calls.
997#'
998#'
999#' @section Life cycle:
1000#'
1001#' These functions are deprecated and replaced by [trace_back()].
1002#'
1003#' @param stack An evaluation stack.
1004#' @param n The number of call frames (not eval frames) to trim off
1005#'   the top of the stack. In other words, the number of layers of
1006#'   intervening frames to trim.
1007#' @export
1008#' @keywords internal
1009#' @examples
1010#' # Intervening frames appear on the evaluation stack:
1011#' identity(identity(ctxt_stack()))
1012#'
1013#' # stack_trim() will trim the first n layers of calls:
1014#' stack_trim(identity(identity(ctxt_stack())))
1015#'
1016#' # Note that it also takes care of calls intervening at its own call
1017#' # site:
1018#' identity(identity(
1019#'   stack_trim(identity(identity(ctxt_stack())))
1020#' ))
1021#'
1022#' # It is especially useful when used within a function that needs to
1023#' # inspect the evaluation stack but should nonetheless be callable
1024#' # within nested calls without side effects:
1025#' stack_util <- function() {
1026#'   # n = 2 means that two layers of intervening calls should be
1027#'   # removed: The layer at ctxt_stack()'s call site (including the
1028#'   # stack_trim() call), and the layer at stack_util()'s call.
1029#'   stack <- stack_trim(ctxt_stack(), n = 2)
1030#'   stack
1031#' }
1032#' user_fn <- function() {
1033#'   # A user calls your stack utility with intervening frames:
1034#'   identity(identity(stack_util()))
1035#' }
1036#' # These intervening frames won't appear in the evaluation stack
1037#' identity(user_fn())
1038stack_trim <- function(stack, n = 1) {
1039  warn_deprecated("`stack_trim()` is deprecated as of rlang 0.3.0.")
1040
1041  if (n < 1) {
1042    return(stack)
1043  }
1044
1045  # Add 1 to discard stack_trim()'s own intervening frames
1046  caller_pos <- call_frame(n + 1, clean = FALSE)$pos
1047
1048  n_frames <- length(stack)
1049  n_skip <- n_frames - caller_pos
1050  stack[seq(n_skip, n_frames)]
1051}
1052
1053
1054#  Tidy eval  --------------------------------------------------------
1055
1056#' Parse text into a quosure
1057#'
1058#' @description
1059#'
1060#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1061#'
1062#' These functions were deprecated and renamed to [parse_quo()]
1063#' and [parse_quos()] in rlang 0.2.0. This is for consistency with the
1064#' convention that suffixes indicating return types are not
1065#' abbreviated.
1066#'
1067#' @inheritParams parse_expr
1068#' @keywords internal
1069#' @export
1070parse_quosure <- function(x, env = caller_env()) {
1071  warn_deprecated(paste_line(
1072    "`parse_quosure()` is deprecated as of rlang 0.2.0.",
1073    "Please use `parse_quo()` instead."
1074  ))
1075  parse_quo(x, env = env)
1076}
1077#' @rdname parse_quosure
1078#' @export
1079parse_quosures <- function(x, env = caller_env()) {
1080  warn_deprecated(paste_line(
1081    "`parse_quosures()` is deprecated as of rlang 0.2.0.",
1082    "Please use `parse_quos()` instead."
1083  ))
1084  parse_quos(x, env = env)
1085}
1086
1087#' Squash a quosure
1088#'
1089#' @description
1090#'
1091#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1092#'
1093#' This function is deprecated, please use [quo_squash()] instead.
1094#'
1095#' @inheritParams quo_squash
1096#' @keywords internal
1097#' @export
1098quo_expr <- function(quo, warn = FALSE) {
1099  warn_deprecated(paste_line(
1100    "`quo_expr()` is deprecated as of rlang 0.2.0.",
1101    "Please use `quo_squash()` instead."
1102  ))
1103  quo_squash(quo, warn = warn)
1104}
1105
1106#' Create an overscope
1107#'
1108#' @description
1109#'
1110#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1111#'
1112#' These functions have been deprecated in rlang 0.2.0. Please use
1113#' [as_data_mask()] and [new_data_mask()] instead. We no longer
1114#' require the mask to be cleaned up so `overscope_clean()` does not
1115#' have a replacement.
1116#'
1117#' @inheritParams as_data_mask
1118#' @param quo A [quosure][nse-defuse].
1119#'
1120#' @keywords internal
1121#' @export
1122as_overscope <- function(quo, data = NULL) {
1123  warn_deprecated(paste_line(
1124    "`as_overscope()` is deprecated as of rlang 0.2.0.",
1125    "Please use `as_data_mask()` instead."
1126  ))
1127  as_data_mask(data)
1128}
1129#' @rdname as_overscope
1130#' @param enclosure The `parent` argument of [new_data_mask()].
1131#' @export
1132new_overscope <- function(bottom, top = NULL, enclosure = NULL) {
1133  warn_deprecated(paste_line(
1134    "`new_overscope()` is deprecated as of rlang 0.2.0.",
1135    "Please use `new_data_mask()` instead."
1136  ))
1137  new_data_mask(bottom, top)
1138}
1139#' @rdname as_overscope
1140#' @param overscope A data mask.
1141#' @export
1142overscope_clean <- function(overscope) {
1143  warn_deprecated("`overscope_clean()` is deprecated as of rlang 0.2.0.")
1144  invisible(.Call(rlang_data_mask_clean, overscope))
1145}
1146
1147#' Evaluate next quosure in a data mask
1148#'
1149#' @description
1150#'
1151#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1152#'
1153#' `overscope_eval_next()` is deprecated as of rlang 0.2.0. Please use
1154#' `eval_tidy()` to which you can now supply an overscope.
1155#'
1156#' @param quo A quosure.
1157#' @param overscope A valid overscope containing bindings for `~`,
1158#'   `.top_env` and `_F` and whose parents contain overscoped bindings
1159#'   for tidy evaluation.
1160#' @param env The lexical enclosure in case `quo` is not a validly
1161#'   scoped quosure. This is the [base environment][base_env] by
1162#'   default.
1163#'
1164#' @keywords internal
1165#' @export
1166overscope_eval_next <- function(overscope, quo, env = base_env()) {
1167  warn_deprecated(paste_line(
1168    "`overscope_eval_next()` is deprecated as of rlang 0.2.0.",
1169    "Please use `eval_tidy()` with a data mask instead."
1170  ))
1171  .External2(rlang_ext2_eval_tidy, quo, overscope, env)
1172}
1173
1174
1175#  Expressions  ------------------------------------------------------
1176
1177#' Create a call
1178#'
1179#' @description
1180#'
1181#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1182#'
1183#' These functions are deprecated, please use [call2()] and
1184#' [new_call()] instead.
1185#'
1186#' @inheritParams call2
1187#' @keywords internal
1188#' @export
1189lang <- function(.fn, ..., .ns = NULL) {
1190  warn_deprecated(paste_line(
1191    "`lang()` is deprecated as of rlang 0.2.0.",
1192    "Please use `call2()` instead."
1193  ))
1194  call2(.fn, ..., .ns = .ns)
1195}
1196#' @rdname lang
1197#' @inheritParams new_call
1198#' @export
1199new_language <- function(head, tail = NULL) {
1200  warn_deprecated(paste_line(
1201    "`new_language()` is deprecated as of rlang 0.2.0.",
1202    "Please use `new_call()` instead."
1203  ))
1204  new_call(head, tail)
1205}
1206
1207#' Is object a call?
1208#'
1209#' @description
1210#'
1211#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1212#'
1213#' These functions are deprecated, please use [is_call()] and its `n`
1214#' argument instead.
1215#'
1216#' @inheritParams is_call
1217#' @keywords internal
1218#' @export
1219is_lang <- function(x, name = NULL, n = NULL, ns = NULL) {
1220  warn_deprecated(paste_line(
1221    "`is_lang()` is deprecated as of rlang 0.2.0.",
1222    "Please use `is_call()` instead."
1223  ))
1224  is_call(x, name, n, ns)
1225}
1226#' @rdname is_lang
1227#' @export
1228is_unary_lang <- function(x, name = NULL, ns = NULL) {
1229  warn_deprecated(paste_line(
1230    "`is_unary_lang()` is deprecated as of rlang 0.2.0.",
1231    "Please use `is_call()` instead."
1232  ))
1233  is_call(x, name, n = 1L, ns = ns)
1234}
1235#' @rdname is_lang
1236#' @export
1237is_binary_lang <- function(x, name = NULL, ns = NULL) {
1238  warn_deprecated(paste_line(
1239    "`is_binary_lang()` is deprecated as of rlang 0.2.0.",
1240    "Please use `is_call()` instead."
1241  ))
1242  is_call(x, name, n = 2L, ns = ns)
1243}
1244#' @rdname is_lang
1245#' @param quo A quosure to test.
1246#' @export
1247quo_is_lang <- function(quo) {
1248  warn_deprecated(paste_line(
1249    "`quo_is_lang()` is deprecated as of rlang 0.2.0.",
1250    "Please use `quo_is_call()` instead."
1251  ))
1252  .Call(rlang_quo_is_call, quo)
1253}
1254
1255#' Manipulate or access a call
1256#'
1257#' @description
1258#'
1259#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1260#'
1261#' These functions are deprecated, please use [call_modify()],
1262#' [call_standardise()], or [call_fn()] instead.
1263#'
1264#' @inheritParams call_modify
1265#' @param lang,.lang The `call` or `.call` argument of the renamed
1266#'   functions.
1267#' @keywords internal
1268#' @export
1269lang_modify <- function(.lang, ..., .standardise = FALSE) {
1270  warn_deprecated(paste_line(
1271    "`lang_modify()` is deprecated as of rlang 0.2.0.",
1272    "Please use `call_modify()` instead."
1273  ))
1274  if (.standardise) {
1275    .lang <- call_standardise(.lang, caller_env())
1276  }
1277  call_modify(.lang, ...)
1278}
1279#' @rdname lang_modify
1280#' @export
1281lang_standardise <- function(lang) {
1282  warn_deprecated(paste_line(
1283    "`lang_standardise()` is deprecated as of rlang 0.2.0.",
1284    "Please use `call_standardise()` instead."
1285  ))
1286  call_standardise(lang, env = caller_env())
1287}
1288#' @rdname lang_modify
1289#' @export
1290lang_fn <- function(lang) {
1291  warn_deprecated(paste_line(
1292    "`lang_fn()` is deprecated as of rlang 0.2.0.",
1293    "Please use `call_fn()` instead."
1294  ))
1295  call_fn(lang, caller_env())
1296}
1297#' @rdname lang_modify
1298#' @export
1299lang_name <- function(lang) {
1300  warn_deprecated(paste_line(
1301    "`lang_name()` is deprecated as of rlang 0.2.0.",
1302    "Please use `call_name()` instead."
1303  ))
1304  call_name(lang)
1305}
1306#' @rdname lang_modify
1307#' @export
1308lang_args <- function(lang) {
1309  warn_deprecated(paste_line(
1310    "`lang_args()` is deprecated as of rlang 0.2.0.",
1311    "Please use `call_args()` instead."
1312  ))
1313  call_args(lang)
1314}
1315#' @rdname lang_modify
1316#' @export
1317lang_args_names <- function(lang) {
1318  warn_deprecated(paste_line(
1319    "`lang_args_names()` is deprecated as of rlang 0.2.0.",
1320    "Please use `call_args_names()` instead."
1321  ))
1322  call_args_names(lang)
1323}
1324
1325
1326#' Return the head or tail of a call
1327#'
1328#' @description
1329#'
1330#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1331#'
1332#' As of rlang 0.2.0 these functions are retired (deprecated for now)
1333#' because they are low level accessors that are rarely needed for end
1334#' users.
1335#'
1336#' @param lang A call.
1337#' @keywords internal
1338#' @export
1339lang_head <- function(lang) {
1340  warn_deprecated("`lang_head()` is deprecated as of rlang 0.2.0.")
1341  call <- get_expr(lang)
1342  stopifnot(is_call(call))
1343  node_car(call)
1344}
1345#' @rdname lang_head
1346#' @export
1347lang_tail <- function(lang) {
1348  warn_deprecated("`lang_tail()` is deprecated as of rlang 0.2.0.")
1349  call <- get_expr(lang)
1350  stopifnot(is_call(call))
1351  node_cdr(call)
1352}
1353
1354#' Is an object an expression?
1355#'
1356#' @description
1357#'
1358#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1359#'
1360#' This function was deprecated and renamed to [is_expression()] in
1361#' rlang 0.2.0. This is for consistency with other type predicates
1362#' which are not abbreviated.
1363#'
1364#' @inheritParams is_expression
1365#' @keywords internal
1366#' @export
1367is_expr <- function(x) {
1368  warn_deprecated(paste_line(
1369    "`is_expr()` is deprecated as of rlang 0.2.0.",
1370    "Please use `is_expression()` instead."
1371  ))
1372  is_expression(x)
1373}
1374
1375
1376#  Nodes  ------------------------------------------------------------
1377
1378#' Mutate node components
1379#'
1380#' @description
1381#'
1382#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1383#'
1384#' These functions were deprecated and renamed with `node_poke_`
1385#' prefix in rlang 0.2.0. This change follows a new naming convention
1386#' where mutation is referred to as "poking".
1387#'
1388#' @inheritParams new_node
1389#'
1390#' @keywords internal
1391#' @export
1392mut_node_car <- function(x, newcar) {
1393  warn_deprecated("`mut_node_car()` is deprecated as of rlang 0.2.0.")
1394  invisible(.Call(rlang_node_poke_car, x, newcar))
1395}
1396#' @rdname mut_node_car
1397#' @export
1398mut_node_cdr <- function(x, newcdr) {
1399  warn_deprecated("`mut_node_cdr()` is deprecated as of rlang 0.2.0.")
1400  invisible(.Call(rlang_node_poke_cdr, x, newcdr))
1401}
1402#' @rdname mut_node_car
1403#' @export
1404mut_node_caar <- function(x, newcar) {
1405  warn_deprecated("`mut_node_caar()` is deprecated as of rlang 0.2.0.")
1406  invisible(.Call(rlang_node_poke_caar, x, newcar))
1407}
1408#' @rdname mut_node_car
1409#' @export
1410mut_node_cadr <- function(x, newcar) {
1411  warn_deprecated("`mut_node_cadr()` is deprecated as of rlang 0.2.0.")
1412  invisible(.Call(rlang_node_poke_cadr, x, newcar))
1413}
1414#' @rdname mut_node_car
1415#' @export
1416mut_node_cdar <- function(x, newcdr) {
1417  warn_deprecated("`mut_node_cdar()` is deprecated as of rlang 0.2.0.")
1418  invisible(.Call(rlang_node_poke_cdar, x, newcdr))
1419}
1420#' @rdname mut_node_car
1421#' @export
1422mut_node_cddr <- function(x, newcdr) {
1423  warn_deprecated("`mut_node_cddr()` is deprecated as of rlang 0.2.0.")
1424  invisible(.Call(rlang_node_poke_cddr, x, newcdr))
1425}
1426#' @rdname mut_node_car
1427#' @export
1428mut_node_tag <- function(x, newtag) {
1429  warn_deprecated("`mut_node_tag()` is deprecated as of rlang 0.2.0.")
1430  invisible(.Call(rlang_node_poke_tag, x, newtag))
1431}
1432
1433#' @rdname vector-old-ctors
1434#' @export
1435node <- function(car, cdr = NULL) {
1436  warn_deprecated(paste_line(
1437    "`node()` is deprecated as of rlang 0.2.0.",
1438    "Please use `new_node()` instead."
1439  ))
1440  new_node(car, cdr)
1441}
1442
1443
1444#  Environments  -----------------------------------------------------
1445
1446#' Coerce to an environment
1447#'
1448#' @description
1449#'
1450#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1451#'
1452#' This function is deprecated as it was renamed to [as_environment()]
1453#' in rlang 0.2.0.
1454#'
1455#' @keywords internal
1456#' @export
1457as_env <- function(x, parent = NULL) {
1458  warn_deprecated("`as_env()` is deprecated as of rlang 0.2.0.")
1459  as_environment(x, parent)
1460}
1461
1462#' Is an object an environment?
1463#'
1464#' @description
1465#'
1466#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1467#'
1468#' These functions were deprecated and renamed to [is_environment()]
1469#' and [is_bare_environment()] in rlang 0.2.0. This is for consistency
1470#' with other type predicates which are not abbreviated.
1471#'
1472#' @inheritParams is_environment
1473#' @keywords internal
1474#' @export
1475is_env <- function(x) {
1476  warn_deprecated(paste_line(
1477    "`is_env()` is deprecated as of rlang 0.2.0.",
1478    "Please use `is_environment()` instead."
1479  ))
1480  is_environment(x)
1481}
1482#' @rdname is_env
1483#' @export
1484is_bare_env <- function(x) {
1485  warn_deprecated(paste_line(
1486    "`is_bare_env()` is deprecated as of rlang 0.2.0.",
1487    "Please use `is_bare_environment()` instead."
1488  ))
1489  is_bare_environment(x)
1490}
1491
1492#' Bind a promise or active binding
1493#'
1494#' @description
1495#'
1496#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1497#'
1498#' As of rlang 0.3.0, `env_bind_exprs()` and `env_bind_fns()` have
1499#' been renamed to [env_bind_lazy()] and [env_bind_active()] for
1500#' consistency.
1501#'
1502#' @inheritParams env_bind
1503#'
1504#' @keywords internal
1505#' @export
1506env_bind_exprs <- function(.env, ..., .eval_env = caller_env()) {
1507  warn_deprecated(paste_line(
1508    "`env_bind_exprs()` is deprecated as of rlang 0.3.0.",
1509    "Please use `env_bind_lazy()` instead."
1510  ))
1511  env_bind_lazy(.env = .env, ..., .eval_env = .eval_env)
1512}
1513#' @rdname env_bind_exprs
1514#' @export
1515env_bind_fns <- function(.env, ...) {
1516  warn_deprecated(paste_line(
1517    "`env_bind_fns()` is deprecated as of rlang 0.3.0.",
1518    "Please use `env_bind_active()` instead."
1519  ))
1520  env_bind_active(.env = .env, ...)
1521}
1522
1523#' Retired `scoped` functions
1524#'
1525#' @description
1526#'
1527#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1528#'
1529#' These functions are deprecated as of rlang 0.3.0. They are replaced
1530#' by [is_attached()], ...
1531#'
1532#' @param nm The name of an environment attached to the search
1533#'   path. Call [base::search()] to see what is currently on the path.
1534#'
1535#' @keywords internal
1536#' @export
1537scoped_env <- function(nm) {
1538  warn_deprecated(paste_line(
1539    "`scoped_env()` is deprecated as of rlang 0.3.0.",
1540    "Please use `search_env()` instead."
1541  ))
1542  local_options(lifecycle_disable_warnings = TRUE)
1543
1544  if (identical(nm, "NULL")) {
1545    return(empty_env())
1546  }
1547  if (!is_scoped(nm)) {
1548    stop(paste0(nm, " is not in scope"), call. = FALSE)
1549  }
1550  as.environment(nm)
1551}
1552#' @rdname scoped_env
1553#' @export
1554is_scoped <- function(nm) {
1555  warn_deprecated(paste_line(
1556    "`is_scoped()` is deprecated as of rlang 0.3.0.",
1557    "Please use `is_attached()` instead."
1558  ))
1559  local_options(lifecycle_disable_warnings = TRUE)
1560
1561  if (!is_scalar_character(nm)) {
1562    stop("`nm` must be a string", call. = FALSE)
1563  }
1564  nm %in% scoped_names()
1565}
1566#' @rdname scoped_env
1567#' @export
1568scoped_envs <- function() {
1569  warn_deprecated(paste_line(
1570    "`scoped_envs()` is deprecated as of rlang 0.3.0.",
1571    "Please use `search_envs()` instead."
1572  ))
1573  local_options(lifecycle_disable_warnings = TRUE)
1574
1575  envs <- c(list(.GlobalEnv), env_parents(.GlobalEnv))
1576  set_names(envs, scoped_names())
1577}
1578#' @rdname scoped_env
1579#' @export
1580scoped_names <- function() {
1581  warn_deprecated(paste_line(
1582    "`scoped_names()` is deprecated as of rlang 0.3.0.",
1583    "Please use `base::search()` instead."
1584  ))
1585  c(search(), "NULL")
1586}
1587
1588
1589#  Vectors  ----------------------------------------------------------
1590
1591#' Retired vector construction by length
1592#'
1593#' @description
1594#'
1595#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1596#'
1597#' These functions were deprecated and renamed with `new_` prefix in
1598#' rlang 0.2.0. This is for consistency with other non-variadic object
1599#' constructors.
1600#'
1601#' @param .x A vector.
1602#' @inheritParams new-vector
1603#' @inheritParams new-vector-along-retired
1604#' @name vector-old-ctors
1605#' @keywords internal
1606NULL
1607
1608#' @rdname vector-old-ctors
1609#' @export
1610lgl_len <- function(.n) {
1611  warn_deprecated(paste_line(
1612    "`lgl_len()` is deprecated as of rlang 0.2.0.",
1613    "Please use `new_logical()` instead."
1614  ))
1615  new_logical(.n)
1616}
1617#' @rdname vector-old-ctors
1618#' @export
1619int_len <- function(.n) {
1620  warn_deprecated(paste_line(
1621    "`int_len()` is deprecated as of rlang 0.2.0.",
1622    "Please use `new_integer()` instead."
1623  ))
1624  new_integer(.n)
1625}
1626#' @rdname vector-old-ctors
1627#' @export
1628dbl_len <- function(.n) {
1629  warn_deprecated(paste_line(
1630    "`dbl_len()` is deprecated as of rlang 0.2.0.",
1631    "Please use `new_double()` instead."
1632  ))
1633  new_double(.n)
1634}
1635#' @rdname vector-old-ctors
1636#' @export
1637chr_len <- function(.n) {
1638  warn_deprecated(paste_line(
1639    "`chr_len()` is deprecated as of rlang 0.2.0.",
1640    "Please use `new_character()` instead."
1641  ))
1642  new_character(.n)
1643}
1644#' @rdname vector-old-ctors
1645#' @export
1646cpl_len <- function(.n) {
1647  warn_deprecated(paste_line(
1648    "`cpl_len()` is deprecated as of rlang 0.2.0.",
1649    "Please use `new_complex()` instead."
1650  ))
1651  new_complex(.n)
1652}
1653#' @rdname vector-old-ctors
1654#' @export
1655raw_len <- function(.n) {
1656  warn_deprecated(paste_line(
1657    "`raw_len()` is deprecated as of rlang 0.2.0.",
1658    "Please use `new_raw()` instead."
1659  ))
1660  new_raw(.n)
1661}
1662#' @rdname vector-old-ctors
1663#' @export
1664bytes_len <- function(.n) {
1665  warn_deprecated(paste_line(
1666    "`bytes_len()` is deprecated as of rlang 0.2.0.",
1667    "Please use `new_raw()` instead."
1668  ))
1669  new_raw(.n)
1670}
1671#' @rdname vector-old-ctors
1672#' @export
1673list_len <- function(.n) {
1674  warn_deprecated(paste_line(
1675    "`list_len()` is deprecated as of rlang 0.2.0.",
1676    "Please use `new_list()` instead."
1677  ))
1678  new_list(.n)
1679}
1680
1681#' @rdname vector-old-ctors
1682#' @export
1683lgl_along <- function(.x) {
1684  warn_deprecated("`lgl_along()` is deprecated as of rlang 0.2.0.")
1685  local_options(lifecycle_disable_warnings = TRUE)
1686  new_logical_along(.x, NULL)
1687}
1688#' @rdname vector-old-ctors
1689#' @export
1690int_along <- function(.x) {
1691  warn_deprecated("`int_along()` is deprecated as of rlang 0.2.0.")
1692  local_options(lifecycle_disable_warnings = TRUE)
1693  new_integer_along(.x, NULL)
1694}
1695#' @rdname vector-old-ctors
1696#' @export
1697dbl_along <- function(.x) {
1698  warn_deprecated("`dbl_along()` is deprecated as of rlang 0.2.0.")
1699  local_options(lifecycle_disable_warnings = TRUE)
1700  new_double_along(.x, NULL)
1701}
1702#' @rdname vector-old-ctors
1703#' @export
1704chr_along <- function(.x) {
1705  warn_deprecated("`chr_along()` is deprecated as of rlang 0.2.0.")
1706  local_options(lifecycle_disable_warnings = TRUE)
1707  new_character_along(.x, NULL)
1708}
1709#' @rdname vector-old-ctors
1710#' @export
1711cpl_along <- function(.x) {
1712  warn_deprecated("`cpl_along()` is deprecated as of rlang 0.2.0.")
1713  local_options(lifecycle_disable_warnings = TRUE)
1714  new_complex_along(.x, NULL)
1715}
1716#' @rdname vector-old-ctors
1717#' @export
1718raw_along <- function(.x) {
1719  warn_deprecated("`raw_along()` is deprecated as of rlang 0.2.0.")
1720  local_options(lifecycle_disable_warnings = TRUE)
1721  new_raw_along(.x, NULL)
1722}
1723#' @rdname vector-old-ctors
1724#' @export
1725bytes_along <- function(.x) {
1726  warn_deprecated("`bytes_along()` is deprecated as of rlang 0.2.0.")
1727  local_options(lifecycle_disable_warnings = TRUE)
1728  new_raw_along(.x, NULL)
1729}
1730#' @rdname vector-old-ctors
1731#' @export
1732list_along <- function(.x) {
1733  warn_deprecated("`list_along()` is deprecated as of rlang 0.2.0.")
1734  local_options(lifecycle_disable_warnings = TRUE)
1735  new_list_along(.x, NULL)
1736}
1737
1738#' Create vectors matching the length of a given vector
1739#'
1740#' These functions are deprecated as of rlang 0.3.0 because they
1741#' are longer to type than the equivalent [rep_along()] or
1742#' [rep_named()] calls without added clarity.
1743#'
1744#' @param x A vector.
1745#' @param names Names for the new vector.
1746#' @name new-vector-along-retired
1747#' @keywords internal
1748
1749#' @export
1750#' @rdname new-vector-along-retired
1751new_logical_along <- function(x, names = base::names(x)) {
1752  warn_deprecated_along("logical", "NA")
1753  set_names_impl(rep_len(na_lgl, length(x)), x, names)
1754}
1755#' @export
1756#' @rdname new-vector-along-retired
1757new_integer_along <- function(x, names = base::names(x)) {
1758  warn_deprecated_along("integer", "na_int")
1759  set_names_impl(rep_len(na_int, length(x)), x, names)
1760}
1761#' @export
1762#' @rdname new-vector-along-retired
1763new_double_along <- function(x, names = base::names(x)) {
1764  warn_deprecated_along("double", "na_dbl")
1765  set_names_impl(rep_len(na_dbl, length(x)), x, names)
1766}
1767#' @export
1768#' @rdname new-vector-along-retired
1769new_character_along <- function(x, names = base::names(x)) {
1770  warn_deprecated_along("character", "na_chr")
1771  set_names_impl(rep_len(na_chr, length(x)), x, names)
1772}
1773#' @export
1774#' @rdname new-vector-along-retired
1775new_complex_along <- function(x, names = base::names(x)) {
1776  warn_deprecated_along("complex", "na_cpl")
1777  set_names_impl(rep_len(na_cpl, length(x)), x, names)
1778}
1779#' @export
1780#' @rdname new-vector-along-retired
1781new_raw_along <- function(x, names = base::names(x)) {
1782  warn_deprecated_along("raw", "new_raw(1)")
1783  set_names_impl(vector("raw", length(x)), x, names)
1784}
1785#' @export
1786#' @rdname new-vector-along-retired
1787new_list_along <- function(x, names = base::names(x)) {
1788  warn_deprecated_along("list", "list(NULL)")
1789  set_names_impl(vector("list", length(x)), x, names)
1790}
1791warn_deprecated_along <- function(type, na) {
1792  warn_deprecated(paste_line(
1793    sprintf("`new_%s_along()` is deprecated as of rlang 0.3.0.", type),
1794    sprintf("Please use `rep_along(x, %s)` or `rep_named(nms, %s)` instead.", na, na)
1795  ))
1796}
1797# FIXME: This can be simplified once the `_along` ctors are defunct
1798set_names_impl <- function(x, mold, nm, ...) {
1799  .Call(rlang_set_names, x, mold, nm, environment())
1800}
1801
1802#' Prepend a vector
1803#'
1804#' @description
1805#'
1806#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1807#'
1808#' Vector functions are now out of scope for rlang. They might be
1809#' revived in the vctrs or funs packages.
1810#'
1811#'
1812#' @keywords internal
1813#'
1814#' @param x the vector to be modified.
1815#' @param values to be included in the modified vector.
1816#' @param before a subscript, before which the values are to be appended.
1817#' @export
1818prepend <- function(x, values, before = 1) {
1819  warn_deprecated_vector("prepend")
1820
1821  n <- length(x)
1822  stopifnot(before > 0 && before <= n)
1823
1824  if (before == 1) {
1825    c(values, x)
1826  } else {
1827    c(x[1:(before - 1)], values, x[before:n])
1828  }
1829}
1830
1831#' @rdname prepend
1832#' @param .x A vector to modify.
1833#' @param ... <[dynamic][dyn-dots]> List of elements to merge into
1834#'   `.x`. Named elements already existing in `.x` are used as
1835#'   replacements. Elements that have new or no names are inserted at
1836#'   the end.
1837#' @export
1838modify <- function(.x, ...) {
1839  warn_deprecated_vector("modify")
1840
1841  out <- as.list(.x)
1842  args <- list2(...)
1843
1844  args_nms <- names(args)
1845  exists <- have_name(args) & args_nms %in% names(out)
1846
1847  for (nm in args_nms[exists]) {
1848    out[[nm]] <- args[[nm]]
1849  }
1850
1851  c(out, args[!exists])
1852}
1853
1854warn_deprecated_vector <- function(fn) {
1855  warn_deprecated(paste_line(
1856    sprintf("`%s()` is deprecated as of rlang 0.4.0.", fn),
1857    "",
1858    "Vector tools are now out of scope for rlang to make it a more",
1859    "focused package."
1860  ))
1861}
1862
1863
1864
1865#  Attributes  -------------------------------------------------------
1866
1867#' Add attributes to an object
1868#'
1869#' @description
1870#'
1871#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("experimental")}
1872#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("deprecated")}
1873#'
1874#' `set_attrs()` adds, changes, or zaps attributes of objects. Pass a
1875#' single unnamed `NULL` argument to zap all attributes. For
1876#' [uncopyable][is_copyable] types, use `mut_attrs()`.
1877#'
1878#' @details
1879#'
1880#' Unlike [structure()], these setters have no special handling of
1881#' internal attributes names like `.Dim`, `.Dimnames` or `.Names`.
1882#'
1883#'
1884#' @section Life cycle:
1885#'
1886#' These functions are deprecated since rlang 0.3.0.
1887#'
1888#' @param .x An object to decorate with attributes.
1889#' @param ... <[dynamic][dyn-dots]> A list of named attributes. Pass
1890#'   a single unnamed `NULL` argument to zap all attributes from `.x`.
1891#' @return `set_attrs()` returns a modified [shallow copy][duplicate]
1892#'   of `.x`. `mut_attrs()` invisibly returns the original `.x`
1893#'   modified in place.
1894#'
1895#' @keywords internal
1896#' @export
1897#' @examples
1898#' set_attrs(letters, names = 1:26, class = "my_chr")
1899#'
1900#' # Splice a list of attributes:
1901#' attrs <- list(attr = "attr", names = 1:26, class = "my_chr")
1902#' obj <- set_attrs(letters, splice(attrs))
1903#' obj
1904#'
1905#' # Zap attributes by passing a single unnamed NULL argument:
1906#' set_attrs(obj, NULL)
1907#' set_attrs(obj, !!! list(NULL))
1908#'
1909#' # Note that set_attrs() never modifies objects in place:
1910#' obj
1911#'
1912#' # For uncopyable types, mut_attrs() lets you modify in place:
1913#' env <- env()
1914#' mut_attrs(env, foo = "bar")
1915#' env
1916set_attrs <- function(.x, ...) {
1917  warn_deprecated("`set_attrs()` is deprecated as of rlang 0.3.0")
1918
1919  if (!is_copyable(.x)) {
1920    abort("`.x` is uncopyable: use `mut_attrs()` to change attributes in place")
1921  }
1922  set_attrs_impl(.x, ...)
1923}
1924#' @rdname set_attrs
1925#' @export
1926mut_attrs <- function(.x, ...) {
1927  warn_deprecated("`set_attrs()` is deprecated as of rlang 0.3.0")
1928
1929  if (is_copyable(.x)) {
1930    abort("`.x` is copyable: use `set_attrs()` to change attributes without side effect")
1931  }
1932  invisible(set_attrs_impl(.x, ...))
1933}
1934set_attrs_impl <- function(.x, ...) {
1935  attrs <- dots_list(...)
1936
1937  # If passed a single unnamed NULL, zap attributes
1938  if (identical(attrs, set_attrs_null)) {
1939    attributes(.x) <- NULL
1940  } else {
1941    attributes(.x) <- c(attributes(.x), attrs)
1942  }
1943
1944  .x
1945}
1946set_attrs_null <- list(NULL)
1947names(set_attrs_null) <- ""
1948
1949
1950#  Conditions --------------------------------------------------------
1951
1952#' Exiting handler
1953#'
1954#' @description
1955#'
1956#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("soft-deprecated")}
1957#'
1958#' `exiting()` is no longer necessary as handlers are exiting by default.
1959#'
1960#' @keywords internal
1961#' @export
1962exiting <- function(handler) {
1963  signal_soft_deprecated(c(
1964    "`exiting()` is soft-deprecated as of rlang 0.4.0.",
1965    "Handlers are now treated as exiting by default."
1966  ))
1967  handler <- as_function(handler)
1968  structure(handler, class = c("rlang_handler_exiting", "rlang_handler", "function"))
1969}
1970
1971
1972#  Scoped_
1973
1974#' Questioning `scoped_` functions
1975#'
1976#' @description
1977#'
1978#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("questioning")}
1979#'
1980#' These functions have been renamed to use the conventional `local_`
1981#' prefix. They will be deprecated in the next minor version of rlang.
1982#'
1983#' @inheritParams local_interactive
1984#' @inheritParams local_options
1985#' @inheritParams local_bindings
1986#'
1987#' @export
1988scoped_interactive <- function(value = TRUE, frame = caller_env()) {
1989  local_interactive(value = value, frame = frame)
1990}
1991#' @rdname scoped_interactive
1992#' @export
1993scoped_options <- function(..., .frame = caller_env()) {
1994  local_options(..., .frame = .frame)
1995}
1996#' @rdname scoped_interactive
1997#' @export
1998scoped_bindings <- function(..., .env = .frame, .frame = caller_env()) {
1999  local_bindings(..., .env = .env, .frame = .frame)
2000}
2001
2002
2003#  Superseded
2004
2005#' Mask bindings by defining symbols deeper in a scope
2006#'
2007#' @description
2008#' \Sexpr[results=rd, stage=render]{rlang:::lifecycle("superseded")}
2009#'
2010#' This function is superseded. Please use [env()] (and possibly
2011#' [set_env()] if you're masking the bindings for another object like
2012#' a closure or a formula) instead.
2013#'
2014#' `env_bury()` is like [env_bind()] but it creates the bindings in a
2015#' new child environment. This makes sure the new bindings have
2016#' precedence over old ones, without altering existing environments.
2017#' Unlike `env_bind()`, this function does not have side effects and
2018#' returns a new environment (or object wrapping that environment).
2019#'
2020#' @inheritParams env_bind
2021#' @return A copy of `.env` enclosing the new environment containing
2022#'   bindings to `...` arguments.
2023#' @seealso [env_bind()], [env_unbind()]
2024#'
2025#' @keywords internal
2026#' @export
2027#' @examples
2028#' orig_env <- env(a = 10)
2029#' fn <- set_env(function() a, orig_env)
2030#'
2031#' # fn() currently sees `a` as the value `10`:
2032#' fn()
2033#'
2034#' # env_bury() will bury the current scope of fn() behind a new
2035#' # environment:
2036#' fn <- env_bury(fn, a = 1000)
2037#' fn()
2038#'
2039#' # Even though the symbol `a` is still defined deeper in the scope:
2040#' orig_env$a
2041env_bury <- function(.env, ...) {
2042  env_ <- get_env(.env)
2043  env_ <- child_env(env_, ...)
2044  set_env(.env, env_)
2045}
2046