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