1 #include <rlang.h>
2 #include "internal.h"
3 
4 
5 static sexp* rlang_env_get_sym(sexp* env, sexp* nm, bool inherit, sexp* closure_env);
6 
rlang_env_get(sexp * env,sexp * nm,sexp * inherit,sexp * closure_env)7 sexp* rlang_env_get(sexp* env, sexp* nm, sexp* inherit, sexp* closure_env) {
8   if (r_typeof(env) != r_type_environment) {
9     r_abort("`env` must be an environment.");
10   }
11   if (!r_is_string(nm, NULL)) {
12     r_abort("`nm` must be a string.");
13   }
14   if (!r_is_bool(inherit)) {
15     r_abort("`inherit` must be a logical value.");
16   }
17 
18   bool c_inherit = r_lgl_get(inherit, 0);
19 
20   sexp* sym = r_str_as_symbol(r_chr_get(nm, 0));
21   return rlang_env_get_sym(env, sym, c_inherit, closure_env);
22 }
23 
24 static
rlang_env_get_sym(sexp * env,sexp * sym,bool inherit,sexp * closure_env)25 sexp* rlang_env_get_sym(sexp* env, sexp* sym, bool inherit, sexp* closure_env) {
26   sexp* out;
27   if (inherit) {
28     out = r_env_find_anywhere(env, sym);
29   } else {
30     out = r_env_find(env, sym);
31   }
32 
33   if (r_typeof(out) == r_type_promise) {
34     KEEP(out);
35     out = r_eval(out, r_empty_env);
36     FREE(1);
37   }
38 
39   if (out == r_syms_unbound) {
40     out = r_eval(r_sym("default"), closure_env);
41   }
42 
43   return out;
44 }
45 
rlang_env_get_list(sexp * env,sexp * nms,sexp * inherit,sexp * closure_env)46 sexp* rlang_env_get_list(sexp* env, sexp* nms, sexp* inherit, sexp* closure_env) {
47   if (r_typeof(env) != r_type_environment) {
48     r_abort("`env` must be an environment.");
49   }
50   if (r_typeof(nms) != r_type_character) {
51     r_abort("`nm` must be a string.");
52   }
53   if (!r_is_bool(inherit)) {
54     r_abort("`inherit` must be a logical value.");
55   }
56 
57   bool c_inherit = r_lgl_get(inherit, 0);
58   r_ssize n = r_length(nms);
59 
60   sexp* out = KEEP(r_new_vector(r_type_list, n));
61   r_poke_names(out, nms);
62 
63   sexp* const * p_nms = r_chr_deref_const(nms);
64 
65   for (r_ssize i = 0; i <n; ++i) {
66     sexp* sym = r_str_as_symbol(p_nms[i]);
67     sexp* elt = rlang_env_get_sym(env, sym, c_inherit, closure_env);
68     r_list_poke(out, i, elt);
69   }
70 
71   FREE(1);
72   return out;
73 }
74 
rlang_env_has(sexp * env,sexp * nms,sexp * inherit)75 sexp* rlang_env_has(sexp* env, sexp* nms, sexp* inherit) {
76   if (r_typeof(env) != r_type_environment) {
77     r_abort("`env` must be an environment.");
78   }
79   if (r_typeof(nms) != r_type_character) {
80     r_abort("`nms` must be a character vector.");
81   }
82   if (r_typeof(inherit) != r_type_logical) {
83     r_abort("`inherit` must be a logical value.");
84   }
85 
86   r_ssize n = r_length(nms);
87   sexp* out = KEEP(r_new_vector(r_type_logical, n));
88 
89   int* p_out = r_lgl_deref(out);
90   sexp* const * p_nms = r_chr_deref_const(nms);
91 
92   if (r_lgl_get(inherit, 0)) {
93     for (r_ssize i = 0; i < n; ++i) {
94       sexp* sym = r_str_as_symbol(p_nms[i]);
95       p_out[i] = r_env_has_anywhere(env, sym);
96     }
97   } else {
98     for (r_ssize i = 0; i < n; ++i) {
99       sexp* sym = r_str_as_symbol(p_nms[i]);
100       p_out[i] = r_env_has(env, sym);
101     }
102   }
103 
104   r_poke_names(out, nms);
105   FREE(1);
106   return out;
107 }
108 
109 static void env_poke_or_zap(sexp* env, sexp* sym, sexp* value);
110 static void env_poke_lazy(sexp* env, sexp* sym, sexp* value, sexp* eval_env);
111 static void env_poke_active(sexp* env, sexp* sym, sexp* fn, sexp* eval_env);
112 static sexp* env_get(sexp* env, sexp* sym);
113 
rlang_env_poke(sexp * env,sexp * nm,sexp * value,sexp * inherit,sexp * create)114 sexp* rlang_env_poke(sexp* env, sexp* nm, sexp* value, sexp* inherit, sexp* create) {
115   if (r_typeof(env) != r_type_environment) {
116     r_abort("`env` must be an environment.");
117   }
118   if (!r_is_string(nm, NULL)) {
119     r_abort("`nm` must be a string.");
120   }
121   if (!r_is_bool(inherit)) {
122     r_abort("`inherit` must be a logical value.");
123   }
124   if (!r_is_bool(create)) {
125     r_abort("`create` must be a logical value.");
126   }
127 
128   bool c_inherit = r_lgl_get(inherit, 0);
129   bool c_create = r_lgl_get(create, 0);
130   sexp* sym = r_str_as_symbol(r_chr_get(nm, 0));
131 
132   sexp* old;
133   if (c_inherit) {
134     old = r_env_find_anywhere(env, sym);
135   } else {
136     old = r_env_find(env, sym);
137   }
138 
139   bool absent = (old == r_syms_unbound);
140   if (absent) {
141     if (!c_create) {
142       r_abort("Can't find existing binding in `env` for \"%s\".",
143               r_sym_get_c_string(sym));
144     }
145     old = rlang_zap;
146   }
147   KEEP(old);
148 
149   if (c_inherit && !absent) {
150     while (env != r_empty_env) {
151       if (r_env_has(env, sym)) {
152         break;
153       }
154       env = r_env_parent(env);
155     }
156   }
157   env_poke_or_zap(env, sym, value);
158 
159   FREE(1);
160   return old;
161 }
162 
163 
164 enum bind_type {
165   BIND_TYPE_value,
166   BIND_TYPE_active,
167   BIND_TYPE_lazy
168 };
169 
parse_bind_type(sexp * bind_type)170 enum bind_type parse_bind_type(sexp* bind_type) {
171   switch (*r_chr_get_c_string(bind_type, 0)) {
172   case 'v': return BIND_TYPE_value;
173   case 'a': return BIND_TYPE_active;
174   case 'l': return BIND_TYPE_lazy;
175   default: never_reached("parse_bind_type");
176   }
177 }
178 
rlang_env_bind(sexp * env,sexp * values,sexp * needs_old,sexp * bind_type,sexp * eval_env)179 sexp* rlang_env_bind(sexp* env,
180                      sexp* values,
181                      sexp* needs_old,
182                      sexp* bind_type,
183                      sexp* eval_env) {
184   if (r_typeof(env) != r_type_environment) {
185     r_abort("`env` must be an environment.");
186   }
187 
188   bool c_needs_old = r_lgl_get(needs_old, 0);
189   enum bind_type c_bind_type = parse_bind_type(bind_type);
190 
191   if (r_typeof(values) != r_type_list) {
192     r_stop_internal("rlang_env_bind", "`values` must be a list.");
193   }
194 
195   r_ssize n = r_length(values);
196   if (!n) {
197     return r_shared_empty_list;
198   }
199 
200   sexp* names = r_names(values);
201   if (n && names == r_null) {
202     r_abort("Can't bind data because some elements are not named.");
203   }
204   sexp* const * p_names = r_chr_deref_const(names);
205 
206   sexp* old = r_null;
207   if (c_needs_old) {
208     old = KEEP(r_new_vector(r_type_list, n));
209     r_poke_names(old, names);
210   } else {
211     KEEP(old);
212   }
213 
214   for (r_ssize i = 0; i < n; ++i) {
215     sexp* sym = r_str_as_symbol(p_names[i]);
216     sexp* value = r_list_get(values, i);
217 
218     if (c_needs_old) {
219       r_list_poke(old, i, env_get(env, sym));
220     }
221 
222     if (value == rlang_zap) {
223       r_env_unbind(env, sym);
224     } else {
225       switch (c_bind_type) {
226       case BIND_TYPE_value: r_env_poke(env, sym, value); break;
227       case BIND_TYPE_lazy: env_poke_lazy(env, sym, value, eval_env); break;
228       case BIND_TYPE_active: env_poke_active(env, sym, value, eval_env); break;
229       }
230     }
231   }
232 
233   FREE(1);
234   return old;
235 }
236 
rlang_env_unbind(sexp * env,sexp * names,sexp * inherits)237 sexp* rlang_env_unbind(sexp* env, sexp* names, sexp* inherits) {
238   if (r_typeof(env) != r_type_environment) {
239     r_abort("`env` must be an environment.");
240   }
241   if (r_typeof(names) != r_type_character) {
242     r_abort("`names` must be a character vector.");
243   }
244   if (!r_is_bool(inherits)) {
245     r_abort("`inherits` must be a logical value.");
246   }
247 
248   if (*r_lgl_deref(inherits)) {
249     r_env_unbind_anywhere_names(env, names);
250   } else {
251     r_env_unbind_names(env, names);
252   }
253 
254   return r_null;
255 }
256 
257 
258 static
env_poke_or_zap(sexp * env,sexp * sym,sexp * value)259 void env_poke_or_zap(sexp* env, sexp* sym, sexp* value) {
260   if (value == rlang_zap) {
261     r_env_unbind(env, sym);
262   } else {
263     r_env_poke(env, sym, value);
264   }
265 }
266 static
env_poke_lazy(sexp * env,sexp * sym,sexp * expr,sexp * eval_env)267 void env_poke_lazy(sexp* env, sexp* sym, sexp* expr, sexp* eval_env) {
268   if (rlang_is_quosure(expr)) {
269     expr = KEEP(r_as_function(expr, eval_env));
270     expr = r_new_call(expr, r_null);
271     FREE(1);
272   }
273   KEEP(expr);
274 
275   r_env_poke_lazy(env, sym, expr, eval_env);
276   FREE(1);
277 }
278 static
env_poke_active(sexp * env,sexp * sym,sexp * fn,sexp * eval_env)279 void env_poke_active(sexp* env, sexp* sym, sexp* fn, sexp* eval_env) {
280   if (!r_is_function(fn)) {
281     fn = r_as_function(fn, eval_env);
282   }
283   KEEP(fn);
284 
285   r_env_poke_active(env, sym, fn);
286   FREE(1);
287 }
288 
289 static
env_get(sexp * env,sexp * sym)290 sexp* env_get(sexp* env, sexp* sym) {
291   sexp* out = r_env_find(env, sym);
292 
293   if (out == r_syms_unbound) {
294     return rlang_zap;
295   }
296 
297   if (r_typeof(out) == r_type_promise) {
298     KEEP(out);
299     out = r_eval(out, r_base_env);
300     FREE(1);
301   }
302 
303   return out;
304 }
305