-
Notifications
You must be signed in to change notification settings - Fork 1k
Expand file tree
/
Copy pathprogramming.c
More file actions
33 lines (31 loc) · 1.38 KB
/
programming.c
File metadata and controls
33 lines (31 loc) · 1.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "data.table.h"
static void substitute_call_arg_names(SEXP expr, SEXP env)
{
if (!length(expr) || !isLanguage(expr))
return; // isLanguage is R's is.call
SEXP arg_names = getAttrib(expr, R_NamesSymbol);
if (!isNull(arg_names)) {
SEXP env_names = getAttrib(env, R_NamesSymbol);
const int *imatches = INTEGER_RO(PROTECT(chmatch(arg_names, env_names, 0)));
const SEXP *env_sub = SEXPPTR_RO(env);
SEXP tmp = expr;
for (int i = 0; i < length(arg_names); i++, tmp = CDR(tmp)) { // substitute call arg names
if (!imatches[i])
continue;
SEXP sym = env_sub[imatches[i] - 1];
if (!isSymbol(sym))
error(_("Attempting to substitute '%s' element with object of type '%s' but it has to be 'symbol' type when substituting name of the call argument, functions 'as.name' and 'I' can be used to work out proper substitution, see ?substitute2 examples."), CHAR(STRING_ELT(arg_names, i)), type2char(TYPEOF(sym)));
SET_TAG(tmp, sym);
}
UNPROTECT(1); // chmatch
}
for (SEXP tmp = expr; tmp != R_NilValue; tmp = CDR(tmp)) { // recursive call to substitute in nested expressions
substitute_call_arg_names(CADR(tmp), env);
}
}
SEXP substitute_call_arg_namesR(SEXP expr, SEXP env) {
SEXP ans = PROTECT(MAYBE_REFERENCED(expr) ? duplicate(expr) : expr);
substitute_call_arg_names(ans, env); // updates in-place
UNPROTECT(1);
return ans;
}