-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce r_wrap_or_clone()
and r_wrap_or_copy()
#1599
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,21 +61,27 @@ r_obj* node_names(r_obj* x) { | |
} | ||
|
||
r_obj* ffi_set_names(r_obj* x, r_obj* mold, r_obj* nm, r_obj* env) { | ||
int n_kept = 0; | ||
|
||
r_obj* dots = KEEP_N(rlang_dots(env), &n_kept); | ||
|
||
if (!r_is_vector(x, -1)) { | ||
r_abort("`x` must be a vector"); | ||
} | ||
|
||
if (nm == r_null) { | ||
x = set_names_dispatch(x, r_null, env); | ||
|
||
FREE(n_kept); | ||
return x; | ||
// Fast case for dropping names | ||
if (r_is_object(x)) { | ||
return set_names_dispatch(x, r_null, env); | ||
} else if (r_names(x) != r_null) { | ||
x = r_wrap_or_clone(x); | ||
r_attrib_poke_names(x, r_null); | ||
return x; | ||
} else { | ||
return x; | ||
} | ||
} | ||
|
||
int n_kept = 0; | ||
|
||
r_obj* dots = KEEP_N(rlang_dots(env), &n_kept); | ||
|
||
if (r_is_function(nm) || r_is_formula(nm, -1, -1)) { | ||
if (r_names(mold) == r_null) { | ||
mold = KEEP_N(eval_as_character(mold, env), &n_kept); | ||
|
@@ -85,12 +91,16 @@ r_obj* ffi_set_names(r_obj* x, r_obj* mold, r_obj* nm, r_obj* env) { | |
|
||
nm = KEEP_N(rlang_as_function(nm, env), &n_kept); | ||
nm = KEEP_N(eval_fn_dots(nm, mold, dots, env), &n_kept); | ||
} else { | ||
if (r_length(dots) > 0) { | ||
nm = KEEP_N(eval_fn_dots(c_fn, nm, dots, env), &n_kept); | ||
} | ||
} else if (r_length(dots) > 0) { | ||
nm = KEEP_N(eval_fn_dots(c_fn, nm, dots, env), &n_kept); | ||
} | ||
|
||
if (r_typeof(nm) != R_TYPE_character || r_is_object(nm)) { | ||
nm = KEEP_N(eval_as_character(nm, env), &n_kept); | ||
|
||
if (r_typeof(nm) != R_TYPE_character) { | ||
r_abort("`nm` must be `NULL` or a character vector."); | ||
} | ||
} | ||
Comment on lines
92
to
104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tweaked this section a little
|
||
|
||
r_ssize n; | ||
|
@@ -100,10 +110,6 @@ r_obj* ffi_set_names(r_obj* x, r_obj* mold, r_obj* nm, r_obj* env) { | |
n = r_length(x); | ||
} | ||
|
||
if (r_typeof(nm) != R_TYPE_character) { | ||
r_abort("`nm` must be `NULL` or a character vector."); | ||
} | ||
|
||
r_ssize nm_n = r_length(nm); | ||
if (nm_n != n) { | ||
if (nm_n != 1) { | ||
|
@@ -118,12 +124,13 @@ r_obj* ffi_set_names(r_obj* x, r_obj* mold, r_obj* nm, r_obj* env) { | |
r_chr_fill(nm, val, n); | ||
} | ||
|
||
if (!is_character(nm, n, OPTION_BOOL_null, OPTION_BOOL_null)) { | ||
r_abort("`nm` must be `NULL` or a character vector the same length as `x`"); | ||
if (r_is_object(x)) { | ||
x = set_names_dispatch(x, nm, env); | ||
} else { | ||
x = r_wrap_or_clone(x); | ||
r_attrib_poke_names(x, nm); | ||
} | ||
|
||
x = set_names_dispatch(x, nm, env); | ||
|
||
FREE(n_kept); | ||
return x; | ||
} | ||
|
@@ -158,9 +165,6 @@ r_obj* names_dispatch(r_obj* x, r_obj* env) { | |
return r_eval(names_call, env); | ||
} | ||
|
||
// Use `names<-()` rather than setting names directly with `r_attrib_poke_names()` | ||
// for genericity and for speed. `names<-()` can shallow duplicate `x`'s | ||
// attributes using ALTREP wrappers, which is not in R's public API. | ||
static inline | ||
r_obj* set_names_dispatch(r_obj* x, r_obj* nm, r_obj* env) { | ||
r_env_poke(env, r_syms.dot_x, x); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved these after the early exit for
nm == NULL
because they aren't needed, just for maximal performance and code clarity