1 #include "rlang.h"
2 #include <Rversion.h>
3 
4 sexp* eval_with_x(sexp* call, sexp* x);
5 sexp* eval_with_xy(sexp* call, sexp* x, sexp* y);
6 sexp* eval_with_xyz(sexp* call, sexp* x, sexp* y, sexp* z);
7 
8 
r_ns_env(const char * pkg)9 sexp* r_ns_env(const char* pkg) {
10   sexp* ns = r_env_find(R_NamespaceRegistry, r_sym(pkg));
11   if (ns == r_syms_unbound) {
12     r_abort("Can't find namespace `%s`", pkg);
13   }
14   return ns;
15 }
16 
ns_env_get(sexp * env,const char * name)17 static sexp* ns_env_get(sexp* env, const char* name) {
18   sexp* obj = KEEP(r_env_find(env, r_sym(name)));
19 
20   // Can be a promise to a lazyLoadDBfetch() call
21   if (r_typeof(obj) == PROMSXP) {
22     obj = r_eval(obj, r_empty_env);
23   }
24   if (obj != r_syms_unbound) {
25     FREE(1);
26     return obj;
27   }
28 
29   // Trigger object not found error
30   r_eval(r_sym(name), env);
31   r_abort("Internal error: `ns_env_get()` should have failed earlier");
32 }
r_base_ns_get(const char * name)33 sexp* r_base_ns_get(const char* name) {
34   return ns_env_get(r_base_env, name);
35 }
36 
37 
38 sexp* rlang_ns_env = NULL;
39 
rlang_ns_get(const char * name)40 sexp* rlang_ns_get(const char* name) {
41   return ns_env_get(rlang_ns_env, name);
42 }
43 
44 
45 static sexp* new_env_call = NULL;
46 static sexp* new_env__parent_node = NULL;
47 static sexp* new_env__size_node = NULL;
48 
r_new_environment(sexp * parent,r_ssize size)49 sexp* r_new_environment(sexp* parent, r_ssize size) {
50   parent = parent ? parent : r_empty_env;
51   r_node_poke_car(new_env__parent_node, parent);
52 
53   size = size ? size : 29;
54   r_node_poke_car(new_env__size_node, r_int(size));
55 
56   sexp* env = r_eval(new_env_call, r_base_env);
57 
58   // Free for gc
59   r_node_poke_car(new_env__parent_node, r_null);
60 
61   return env;
62 }
63 
64 
65 static sexp* env2list_call = NULL;
66 static sexp* list2env_call = NULL;
67 
68 sexp* r_env_as_list_compat(sexp* env, sexp* out);
69 
r_env_as_list(sexp * env)70 sexp* r_env_as_list(sexp* env) {
71   sexp* out = KEEP(eval_with_x(env2list_call, env));
72 
73 #if R_VERSION < R_Version(4, 0, 0)
74   out = r_env_as_list_compat(env, out);
75 #endif
76 
77   FREE(1);
78   return out;
79 }
80 
81 // On R < 4.0, the active binding function is returned instead of
82 // its value. We invoke the active bindings here to get consistent
83 // behaviour in all supported R versions.
r_env_as_list_compat(sexp * env,sexp * out)84 sexp* r_env_as_list_compat(sexp* env, sexp* out) {
85   sexp* nms = KEEP(r_env_names(env));
86   sexp* types = KEEP(r_env_binding_types(env, nms));
87 
88   if (types == R_NilValue) {
89     FREE(2);
90     return out;
91   }
92 
93   r_ssize n = r_length(nms);
94   sexp* const * p_nms = r_chr_deref_const(nms);
95   const int* p_types = r_int_deref_const(types);
96 
97   for (r_ssize i = 0; i < n; ++i) {
98     enum r_env_binding_type type = p_types[i];
99     if (type == R_ENV_BINDING_ACTIVE) {
100       r_ssize fn_idx = r_chr_detect_index(nms, r_str_deref(p_nms[i]));
101       if (fn_idx < 0) {
102         r_abort("Internal error: Can't find active binding in list");
103       }
104 
105       sexp* fn = r_list_get(out, fn_idx);
106       sexp* value = r_eval(KEEP(r_call(fn)), r_empty_env);
107       r_list_poke(out, fn_idx, value);
108       FREE(1);
109     }
110   }
111 
112   FREE(2);
113   return out;
114 }
115 
r_list_as_environment(sexp * x,sexp * parent)116 sexp* r_list_as_environment(sexp* x, sexp* parent) {
117   parent = parent ? parent : r_empty_env;
118   return eval_with_xy(list2env_call, x, parent);
119 }
120 
r_env_clone(sexp * env,sexp * parent)121 sexp* r_env_clone(sexp* env, sexp* parent) {
122   if (parent == NULL) {
123     parent = r_env_parent(env);
124   }
125 
126   sexp* out = KEEP(r_env_as_list(env));
127   out = r_list_as_environment(out, parent);
128 
129   FREE(1);
130   return out;
131 }
132 
133 
134 static sexp* poke_lazy_call = NULL;
135 static sexp* poke_lazy_value_node = NULL;
136 
r_env_poke_lazy(sexp * env,sexp * sym,sexp * expr,sexp * eval_env)137 void r_env_poke_lazy(sexp* env, sexp* sym, sexp* expr, sexp* eval_env) {
138   sexp* name = KEEP(r_sym_as_character(sym));
139 
140   r_node_poke_car(poke_lazy_value_node, expr);
141   r_eval_with_xyz(poke_lazy_call, rlang_ns_env, name, env, eval_env);
142   r_node_poke_car(poke_lazy_value_node, r_null);
143 
144   FREE(1);
145 }
146 
147 
148 static sexp* remove_call = NULL;
149 
150 #if (R_VERSION < R_Version(4, 0, 0))
r__env_unbind(sexp * env,sexp * sym)151 void r__env_unbind(sexp* env, sexp* sym) {
152   // Check if binding exists to avoid `rm()` warning
153   if (r_env_has(env, sym)) {
154     sexp* nm = KEEP(r_sym_as_character(sym));
155     eval_with_xyz(remove_call, env, nm, r_shared_false);
156     FREE(1);
157   }
158 }
159 #endif
160 
r_env_unbind_anywhere(sexp * env,sexp * sym)161 void r_env_unbind_anywhere(sexp* env, sexp* sym) {
162   while (env != r_empty_env) {
163     if (r_env_has(env, sym)) {
164       r_env_unbind(env, sym);
165       return;
166     }
167 
168     env = r_env_parent(env);
169   }
170 }
171 
r_env_unbind_syms(sexp * env,sexp ** syms)172 void r_env_unbind_syms(sexp* env, sexp** syms) {
173   while (syms) {
174     r_env_unbind(env, *syms++);
175   }
176 }
177 
178 static
env_unbind_names(sexp * env,sexp * names,bool inherit)179 void env_unbind_names(sexp* env, sexp* names, bool inherit) {
180   sexp* const * p_names = r_chr_deref_const(names);
181   r_ssize n = r_length(names);
182 
183   if (inherit) {
184     for (r_ssize i = 0; i < n; ++i) {
185       sexp* sym = r_str_as_symbol(p_names[i]);
186       r_env_unbind_anywhere(env, sym);
187     }
188   } else {
189     for (r_ssize i = 0; i < n; ++i) {
190       sexp* sym = r_str_as_symbol(p_names[i]);
191       r_env_unbind(env, sym);
192     }
193   }
194 }
195 
r_env_unbind_names(sexp * env,sexp * names)196 void r_env_unbind_names(sexp* env, sexp* names) {
197   env_unbind_names(env, names, false);
198 }
r_env_unbind_anywhere_names(sexp * env,sexp * names)199 void r_env_unbind_anywhere_names(sexp* env, sexp* names) {
200   env_unbind_names(env, names, true);
201 }
202 
r_env_unbind_strings(sexp * env,const char ** names)203 void r_env_unbind_strings(sexp* env, const char** names) {
204   sexp* nms = KEEP(r_new_character(names));
205   r_env_unbind_names(env, nms);
206   FREE(1);
207 }
r_env_unbind_anywhere_strings(sexp * env,const char ** names)208 void r_env_unbind_anywhere_strings(sexp* env, const char** names) {
209   sexp* nms = KEEP(r_new_character(names));
210   r_env_unbind_anywhere_names(env, nms);
211   FREE(1);
212 }
213 
r_env_unbind_string(sexp * env,const char * name)214 void r_env_unbind_string(sexp* env, const char* name) {
215   static const char* names[2] = { "", NULL };
216   names[0] = name;
217   r_env_unbind_strings(env, names);
218 }
r_env_unbind_string_anywhere(sexp * env,const char * name)219 void r_env_unbind_string_anywhere(sexp* env, const char* name) {
220   static const char* names[2] = { "", NULL };
221   names[0] = name;
222   r_env_unbind_anywhere_strings(env, names);
223 }
224 
r_env_inherits(sexp * env,sexp * ancestor,sexp * top)225 bool r_env_inherits(sexp* env, sexp* ancestor, sexp* top) {
226   top = top ? top : r_empty_env;
227 
228   if (r_typeof(env) != r_type_environment) {
229     r_abort("`env` must be an environment");
230   }
231   if (r_typeof(ancestor) != r_type_environment) {
232     r_abort("`ancestor` must be an environment");
233   }
234   if (r_typeof(top) != r_type_environment) {
235     r_abort("`top` must be an environment");
236   }
237 
238   if (env == r_empty_env) {
239     return false;
240   }
241 
242   while (env != top && env != r_empty_env) {
243     if (env == ancestor) {
244       return true;
245     }
246     env = r_env_parent(env);;
247   }
248 
249   return env == ancestor;
250 }
251 
r_init_rlang_ns_env()252 void r_init_rlang_ns_env() {
253   rlang_ns_env = r_ns_env("rlang");
254 }
255 
256 sexp* r_methods_ns_env = NULL;
257 
r_init_library_env()258 void r_init_library_env() {
259   new_env_call = r_parse_eval("as.call(list(new.env, TRUE, NULL, NULL))", r_base_env);
260   r_mark_precious(new_env_call);
261 
262   new_env__parent_node = r_node_cddr(new_env_call);
263   new_env__size_node = r_node_cdr(new_env__parent_node);
264 
265   env2list_call = r_parse("as.list.environment(x, all.names = TRUE)");
266   r_mark_precious(env2list_call);
267 
268   list2env_call = r_parse("list2env(x, envir = NULL, parent = y, hash = TRUE)");
269   r_mark_precious(list2env_call);
270 
271   poke_lazy_call = r_parse("delayedAssign(x, value = NULL, assign.env = y, eval.env = z)");
272   r_mark_precious(poke_lazy_call);
273 
274   poke_lazy_value_node = r_node_cddr(poke_lazy_call);
275 
276   remove_call = r_parse("remove(list = y, envir = x, inherits = z)");
277   r_mark_precious(remove_call);
278 
279   r_methods_ns_env = r_parse_eval("asNamespace('methods')", r_base_env);
280 }
281