1use ::rdll::*;
7use ::storage::*;
8use ::traits::*;
9use ::rtype::*;
10use ::error::*;
11use std::convert::*;
12
13use ::util::*;
14
15use eval::*;
16use ::symbol::*;
17use ::protect::stackp::*;
18
19pub type Envir = EnvirM<Preserve>;
20pub type EnvirN = EnvirM<NoProtect>;
21
22use std::str::FromStr;
23
24gen_traits_sexp!(EnvirM);
25
26impl<T: SEXPbucket> FromStr for EnvirM<T> {
27 type Err = RError;
28 fn from_str(name: &str) -> RResult<EnvirM<T>> {
29 unsafe {
30
31 if name == ".GlobalEnv" {
33 Ok(EnvirM { data: T::new(R_GlobalEnv) })
34 } else if name == "package:base" {
35 Ok(EnvirM { data: T::new(R_BaseEnv) })
36 } else {
37 let as_environment_sym = Rf_install(c_str("as.environment").as_ptr());
38 let res = rustr_eval(Rf_lang2(as_environment_sym,
39 Rf_mkString(c_str(name).as_ptr())),
40 R_GlobalEnv);
41 match res {
42 Ok(aa) => Ok(EnvirM { data: T::new(aa) }),
43 Err(_) => rraise("fail to create enviroment"),
44 }
45 }
46 }
47 }
48}
49
50impl<T: SEXPbucket> EnvirM<T> {
51 pub fn from_sexp<TT: ToSEXP>(s: TT) -> RResult<EnvirM<T>> {
52 unsafe {
53 if RTYPEOF(s.s()) == ENVSXP {
54 return Ok(EnvirM { data: T::new(s.s()) });
55 }
56 Ok(EnvirM {
57 data: T::new(rustr_eval(Rf_lang2(Rf_install(c_str("as.environment")
58 .as_ptr()),
59 s.s()),
60 R_GlobalEnv)?),
61 })
62 }
63 }
64 pub unsafe fn from_sexp_envir(x: SEXP) -> EnvirM<T> {
65 EnvirM { data: T::new(x) }
66 }
67 pub fn set<E: ToSEXP>(&mut self, x: E) -> RResult<()> {
68 match EnvirM::<T>::from_sexp(unsafe { x.s() }) {
69 Ok(res) => {
70 self.data.set(unsafe { res.s() });
71 Ok(())
72 }
73 Err(e) => rraise(e),
74 }
75 }
76
77 pub fn new<E: ToSEXP>(x: E) -> RResult<EnvirM<T>> {
78 match EnvirM::<T>::from_sexp(unsafe { x.s() }) {
79 Ok(res) => Ok(EnvirM { data: unsafe { T::new(res.s()) } }),
80 Err(e) => rraise(e),
81 }
82 }
83
84 pub fn from_pos(pos: ::std::os::raw::c_int) -> RResult<EnvirM<T>> {
85 unsafe {
86 let as_environment_sym = Rf_install(c_str("as.environment").as_ptr());
87 let res = rustr_eval(Rf_lang2(as_environment_sym, Rf_ScalarInteger(pos)),
88 R_GlobalEnv);
89 match res {
90 Ok(aa) => Ok(EnvirM { data: T::new(aa) }),
91 Err(e) => rraise(e),
92 }
93 }
94 }
95 fn is_user_database(&self) -> bool {
99 unsafe {
100 OBJECT(self.data.s()) == 1 &&
101 Rf_inherits(self.data.s(), c_str("UserDefinedDatabase").as_ptr()) == Rboolean::TRUE
102 }
103 }
104 pub fn global() -> EnvirM<NoProtect> {
105 unsafe { EnvirM { data: NoProtect::new(R_GlobalEnv) } }
106 }
107
108 pub fn empty() -> EnvirM<T> {
109 unsafe { EnvirM { data: T::new(R_EmptyEnv) } }
110 }
111
112 pub fn base() -> EnvirM<T> {
113 unsafe { EnvirM { data: T::new(R_BaseEnv) } }
114 }
115
116 pub fn base_namespace() -> EnvirM<T> {
117 unsafe { EnvirM { data: T::new(R_BaseNamespace) } }
118 }
119 pub fn namespace_env(package: &str) -> RResult<EnvirM<T>> {
120 unsafe {
121 let get_namespace_sym = Rf_install(c_str("getNamespace").as_ptr());
122 let env = rustr_eval(Rf_lang2(get_namespace_sym, Rf_mkString(c_str(package).as_ptr())),
123 R_GlobalEnv);
124 match env {
125 Ok(aa) => Ok(EnvirM { data: T::new(aa) }),
126 Err(e) => rraise(e),
127 }
128 }
129
130 }
131 pub fn parent(&self) -> EnvirM<T> {
132 unsafe { EnvirM { data: T::new(ENCLOS(self.data.s())) } }
133 }
134
135 pub fn new_child(&self, hashed: ::std::os::raw::c_int) -> RResult<EnvirM<T>> {
139 unsafe {
140 let new_env_sym = cstr_sym("new.env");
141 let sexp = rustr_eval(Rf_lang3(new_env_sym,
142 Rf_ScalarLogical(hashed),
143 self.data.s()),
144 R_GlobalEnv)?;
145
146 Ok(EnvirM { data: T::new(sexp) })
147 }
148 }
149 pub fn ls<D: RNew>(&self, all: Rboolean) -> RResult<D> {
150
151 unsafe {
152 if self.is_user_database() {
153 let tb: *mut R_ObjectTable =
154 ::std::mem::transmute(R_ExternalPtrAddr(HASHTAB(self.data.s())));
155 match (*tb).objects {
156 Some(resfn) => D::rnew(resfn(tb)),
157 None => rraise("ls() R_ExternalPtrAddr is invalid."),
158 }
159 } else {
160
161 D::rnew(R_lsInternal(self.data.s(), all))
162 }
163 }
164 }
165 pub fn get<D: RNew>(&self, name: &str) -> RResult<D> {
166 unsafe {
167 let res = Rf_findVarInFrame(self.data.s(), Symbol::from(name).s());
168
169 if res == R_UnboundValue {
170 return D::rnew(R_NilValue);
171 }
172
173 if RTYPEOF(res) == PROMSXP {
175 let res2 = Rf_eval(res, self.data.s());
176 return D::rnew(res2);
177 }
178 D::rnew(res)
179 }
180 }
181 pub fn find<D: RNew>(&self, name: &str) -> RResult<D> {
182 unsafe {
183 let res = Rf_findVar(Symbol::from(name).s(), self.data.s());
184
185 if res == R_UnboundValue {
186 return rraise(format!("binding not found: {:?}", name));
187 }
188 if RTYPEOF(res) == PROMSXP {
190 let res2 = Rf_eval(res, self.data.s());
191 return D::rnew(res2);
192 }
193
194 D::rnew(res)
195 }
196
197 }
198
199 pub fn exists(&self, name: &str) -> bool {
200 unsafe {
201 let res = Rf_findVarInFrame(self.data.s(), Symbol::from(name).s());
202 res != R_UnboundValue
203 }
204 }
205 #[allow(non_snake_case)]
206 pub fn bindingIsLocked(&self, name: &str) -> RResult<bool> {
207 if !self.exists(name) {
208 return rraise(format!("no such binding: {:?}", name));
209 }
210 unsafe { Ok(R_BindingIsLocked(Symbol::from(name).s(), self.data.s()) == Rboolean::TRUE) }
211
212 }
213
214 pub fn assign<E: ToSEXP>(&self, name: &str, x: E) -> RResult<()> {
215
216 match self.bindingIsLocked(name) {
217 Ok(xx) => {
218 if self.exists(name) && xx {
219 return rraise(format!("binding_is_locked: {:?}", name));
220 }
221 }
222 Err(_) => {
223 return rraise(format!("no such binding: {:?}", name));
224 }
225 }
226 unsafe {
227 let name_sym = Rf_install(c_str(name).as_ptr());
228
229 Rf_defineVar(name_sym, x.s(), self.data.s());
230 Ok(())
231 }
232
233 }
234 pub fn is_locked(&self) -> bool {
235 unsafe { R_EnvironmentIsLocked(self.data.s()) == Rboolean::TRUE }
236 }
237
238 pub fn binding_is_active(&self, name: &str) -> RResult<bool> {
239 if !self.exists(name) {
240 return rraise(format!("no such binding: {:?}", name));
241 }
242 unsafe { Ok(R_BindingIsActive(Symbol::from(name).s(), self.data.s()) == Rboolean::TRUE) }
243 }
244 pub fn lock(&self, bindings: Rboolean) {
245 unsafe {
246 R_LockEnvironment(self.data.s(), bindings);
247 }
248 }
249
250 pub fn lock_binding(&self, name: &str) -> RResult<()> {
251 if !self.exists(name) {
252 return rraise(format!("no such binding: {:?}", name));
253 }
254 unsafe {
255 R_LockBinding(Symbol::from(name).s(), self.data.s());
256 Ok(())
257 }
258
259 }
260
261 pub fn unlock_binding(&self, name: &str) -> RResult<()> {
262 if !self.exists(name) {
263 return rraise(format!("no such binding: {:?}", name));
264 }
265 unsafe {
266 R_unLockBinding(Symbol::from(name).s(), self.data.s());
267 Ok(())
268 }
269 }
270 pub fn remove(&self, name: &str) -> RResult<bool> {
274 if self.exists(name) {
275 let res1 = match self.bindingIsLocked(name) {
276 Ok(aa) => aa,
277 Err(_) => {
278 return rraise(format!("no such binding: {:?}", name));
279 }
280 };
281 if res1 {
282 return rraise(format!("binding is locked: {}", name));
283 } else {
284 unsafe {
285 let internal_sym = Rf_install(c_str(".Internal").as_ptr());
288 let remove_sym = Rf_install(c_str("remove").as_ptr());
289 let call = Shield::new(Rf_lang2(internal_sym,
290 Rf_lang4(remove_sym,
291 Rf_mkString(c_str(name).as_ptr()),
292 self.data.s(),
293 Rf_ScalarLogical(0))));
294 Rf_eval(call.s(), R_GlobalEnv);
295 }
296
297 }
298 } else {
299 return rraise(format!("no such binding: {:?}", name));
300 }
301 Ok(true)
302
303 }
304}