1use crate as extendr_api;
2use crate::*;
3use extendr_ffi::{
4 R_BaseNamespace, R_BlankScalarString, R_BlankString, R_NaString, R_NilValue, R_Srcref,
5 R_dot_Generic,
6};
7
8pub fn global_function<K: Into<Robj>>(key: K) -> Result<Robj> {
17 let key = key.into();
18 Environment::global().find_function(key)
19}
20
21pub fn find_namespace<K: Into<Robj>>(key: K) -> Result<Environment> {
33 let key = key.into();
34 let res = single_threaded(|| call!(".getNamespace", key.clone()));
35 if let Ok(res) = res {
36 Ok(res.try_into()?)
37 } else {
38 Err(Error::NamespaceNotFound(key))
39 }
40}
41
42#[deprecated(since = "0.10.0", note = "Use `Environment::current()` instead")]
51pub fn current_env() -> Environment {
52 Environment::current()
53}
54
55#[deprecated(since = "0.10.0", note = "Use `Environment::global()` instead")]
65pub fn global_env() -> Environment {
66 Environment::global()
67}
68
69#[deprecated(since = "0.10.0", note = "Use `Environment::empty()` instead")]
71pub fn empty_env() -> Environment {
72 Environment::empty()
73}
74
75#[cfg(use_r_newenv)]
86pub fn new_env(parent: Environment, hash: bool, capacity: i32) -> Environment {
87 use extendr_ffi::R_NewEnv;
88 single_threaded(|| unsafe {
89 let env = R_NewEnv(parent.robj.get(), hash as i32, capacity);
90 Robj::from_sexp(env).try_into().unwrap()
91 })
92}
93
94#[cfg(not(use_r_newenv))]
96pub fn new_env(parent: Environment, hash: bool, capacity: i32) -> Environment {
97 call!("new.env", hash, parent, capacity)
98 .unwrap()
99 .try_into()
100 .unwrap()
101}
102
103#[deprecated(since = "0.10.0", note = "Use `Environment::base()` instead")]
105pub fn base_env() -> Environment {
106 Environment::base()
107}
108
109pub fn base_namespace() -> Environment {
118 unsafe { Robj::from_sexp(R_BaseNamespace).try_into().unwrap() }
119}
120
121pub fn srcref() -> Robj {
123 unsafe { Robj::from_sexp(R_Srcref) }
124}
125
126pub fn nil_value() -> Robj {
128 unsafe { Robj::from_sexp(R_NilValue) }
129}
130
131pub fn dot_generic() -> Robj {
133 unsafe { Robj::from_sexp(R_dot_Generic) }
134}
135
136pub fn na_string() -> Robj {
138 unsafe { Robj::from_sexp(R_NaString) }
139}
140
141pub fn blank_string() -> Robj {
143 unsafe { Robj::from_sexp(R_BlankString) }
144}
145
146pub fn blank_scalar_string() -> Robj {
148 unsafe { Robj::from_sexp(R_BlankScalarString) }
149}
150
151pub fn parse(code: &str) -> Result<Expressions> {
160 single_threaded(|| unsafe {
161 use extendr_ffi::{ParseStatus, R_NilValue, R_ParseVector};
162 let mut status = ParseStatus::PARSE_NULL;
163 let status_ptr = (&mut status) as *mut _;
164 let codeobj: Robj = code.into();
165 let parsed = Robj::from_sexp(R_ParseVector(codeobj.get(), -1, status_ptr, R_NilValue));
166 match status {
167 ParseStatus::PARSE_OK => parsed.try_into(),
168 _ => Err(Error::ParseError {
169 status,
170 code: code.into(),
171 }),
172 }
173 })
174}
175
176pub fn eval_string(code: &str) -> Result<Robj> {
186 single_threaded(|| {
187 let expr = parse(code)?;
188 let mut res = Robj::from(());
189 if let Some(expr) = expr.as_expressions() {
190 for lang in expr.values() {
191 res = lang.eval()?
192 }
193 }
194 Ok(res)
195 })
196}
197
198pub fn eval_string_with_params(code: &str, values: &[&Robj]) -> Result<Robj> {
210 single_threaded(|| {
211 let env = Environment::new_with_parent(Environment::global());
212 for (i, &v) in values.iter().enumerate() {
213 let key = Symbol::from_string(format!("param.{}", i));
214 env.set_local(key, v);
215 }
216
217 let expr = parse(code)?;
218 let mut res = Robj::from(());
219 if let Some(expr) = expr.as_expressions() {
220 for lang in expr.values() {
221 res = lang.eval_with_env(&env)?
222 }
223 }
224
225 Ok(res)
226 })
227}
228
229pub fn find_namespaced_function(name: &str) -> Result<Language> {
241 let mut iter = name.split("::");
242 match (iter.next(), iter.next(), iter.next()) {
243 (Some(key), None, None) => {
244 let gf = global_function(Symbol::from_string(key))?;
245 Ok(Language::from_values(&[gf]))
246 }
247 (Some(ns), Some(key), None) => {
248 let namespace = find_namespace(ns)?;
249 Ok(Language::from_values(&[
250 namespace.local(Symbol::from_string(key))?
251 ]))
252 }
253 _ => Err(Error::NotFound(r!(name))),
254 }
255}