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
151#[deprecated(since = "0.10.0", note = "Use Expressions::from_str() instead")]
160pub fn parse(code: &str) -> Result<Expressions> {
161 Expressions::from_str(code)
162}
163
164pub fn eval_string(code: &str) -> Result<Robj> {
174 single_threaded(|| {
175 let expr = Expressions::from_str(code)?;
176 let mut res = Robj::from(());
177 if let Some(expr) = expr.as_expressions() {
178 for lang in expr.values() {
179 res = lang.eval()?
180 }
181 }
182 Ok(res)
183 })
184}
185
186pub fn eval_string_with_params(code: &str, values: &[&Robj]) -> Result<Robj> {
198 single_threaded(|| {
199 let env = Environment::new_with_parent(Environment::global());
200 for (i, &v) in values.iter().enumerate() {
201 let key = Symbol::from_string(format!("param.{}", i));
202 env.set_local(key, v);
203 }
204
205 let expr = Expressions::from_str(code)?;
206 let mut res = Robj::from(());
207 if let Some(expr) = expr.as_expressions() {
208 for lang in expr.values() {
209 res = lang.eval_with_env(&env)?
210 }
211 }
212
213 Ok(res)
214 })
215}
216
217pub fn find_namespaced_function(name: &str) -> Result<Language> {
229 let mut iter = name.split("::");
230 match (iter.next(), iter.next(), iter.next()) {
231 (Some(key), None, None) => {
232 let gf = global_function(Symbol::from_string(key))?;
233 Ok(Language::from_values(&[gf]))
234 }
235 (Some(ns), Some(key), None) => {
236 let namespace = find_namespace(ns)?;
237 Ok(Language::from_values(&[
238 namespace.local(Symbol::from_string(key))?
239 ]))
240 }
241 _ => Err(Error::NotFound(r!(name))),
242 }
243}