in src/RStuff/RUtil.h [314:396]
inline void walkObjectsImpl(Func const& f, std::unordered_set<SEXP> &visited, SEXP x) {
if (x == R_NilValue || x == R_UnboundValue || TYPEOF(x) == CHARSXP || visited.count(x)) return;
visited.insert(x);
f(x);
switch (TYPEOF(x)) {
case SYMSXP: {
walkObjectsImpl(f, visited, PRINTNAME(x));
walkObjectsImpl(f, visited, SYMVALUE(x));
walkObjectsImpl(f, visited, INTERNAL(x));
break;
}
case DOTSXP:
case LANGSXP:
case LISTSXP: {
// sxpinfo.extra may contain an immediate binding, meaning that CAR(x) should not be called
// See: https://github.com/r-devel/r-svn/blob/trunk/doc/notes/immbnd.md
if (!x->sxpinfo.extra) walkObjectsImpl(f, visited, CAR(x));
walkObjectsImpl(f, visited, CDR(x));
walkObjectsImpl(f, visited, TAG(x));
break;
}
case CLOSXP: {
walkObjectsImpl(f, visited, FORMALS(x));
walkObjectsImpl(f, visited, BODY(x));
walkObjectsImpl(f, visited, CLOENV(x));
break;
}
case ENVSXP: {
if (x == R_BaseEnv || x == R_BaseNamespace) {
ShieldSEXP names = RI->ls(R_BaseEnv, named("all.names", true));
if (names.type() == STRSXP) {
int length = names.length();
for (int i = 0; i < length; ++i) {
walkObjectsImpl(f, visited, RI->baseEnv.getVar(stringEltNative(names, i), false));
}
}
} else if (x != R_EmptyEnv) {
walkObjectsImpl(f, visited, ENCLOS(x));
walkObjectsImpl(f, visited, FRAME(x));
walkObjectsImpl(f, visited, HASHTAB(x));
}
break;
}
case PROMSXP: {
walkObjectsImpl(f, visited, PRVALUE(x));
walkObjectsImpl(f, visited, PRCODE(x));
walkObjectsImpl(f, visited, PRENV(x));
break;
}
case STRSXP: {
R_xlen_t length = Rf_xlength(x);
for (R_xlen_t i = 0; i < length; ++i) {
walkObjectsImpl(f, visited, STRING_ELT(x, i));
}
break;
}
case EXPRSXP:
case VECSXP: {
R_xlen_t length = Rf_xlength(x);
for (R_xlen_t i = 0; i < length; ++i) {
walkObjectsImpl(f, visited, VECTOR_ELT(x, i));
}
break;
}
case BCODESXP: {
walkObjectsImpl(f, visited, BCODE_CODE(x));
walkObjectsImpl(f, visited, BCODE_CONSTS(x));
walkObjectsImpl(f, visited, BCODE_EXPR(x));
break;
}
case EXTPTRSXP: {
walkObjectsImpl(f, visited, EXTPTR_PROT(x));
walkObjectsImpl(f, visited, EXTPTR_TAG(x));
break;
}
case WEAKREFSXP: {
walkObjectsImpl(f, visited, R_WeakRefKey(x));
walkObjectsImpl(f, visited, R_WeakRefValue(x));
break;
}
}
walkObjectsImpl(f, visited, ATTRIB(x));
}