rustr/
rfunction.rs

1//! R Function type
2//!
3//!
4//!
5
6
7use ::rdll::*;
8use ::storage::*;
9use ::traits::*;
10use ::rtype::*;
11use ::error::*;
12use std::convert::*;
13
14use symbol::*;
15
16use environment::*;
17use protect::stackp::*;
18use eval::*;
19use grow::*;
20
21
22pub type RFun = RFunM<Preserve>;
23
24
25impl<T: SEXPbucket> NewRObj for RFunM<T> {
26    fn new<E: ToSEXP>(x: E) -> RResult<Self> {
27        match unsafe { RTYPEOF(x.s()) } {
28            CLOSXP | SPECIALSXP | BUILTINSXP => unsafe { Ok(RFunM { data: T::new(x.s()) }) },
29            _ => rraise("cannot convert to function"),
30        }
31    }
32    unsafe fn unew<E: ToSEXP>(x: E) -> Self {
33        RFunM { data: T::new(x.s()) }
34    }
35}
36
37impl<T: SEXPbucket> RFunM<T> {
38    pub fn set_sexp<S: ToSEXP>(&mut self, x: S) -> RResult<()> {
39
40        match unsafe { RTYPEOF(x.s()) } {
41            CLOSXP | SPECIALSXP | BUILTINSXP => {
42                self.data.set(unsafe { x.s() });
43                Ok(())
44            }
45            _ => rraise("cannot convert to function"),
46        }
47    }
48    pub fn from_str_global(x: &str) -> RResult<RFunM<T>> {
49        let sym = Symbol::from(x);
50        unsafe { RFunM::new(Rf_findFun(sym.s(), R_GlobalEnv)) }
51    }
52    pub fn from_str<EE: SEXPbucket>(x: &str, env: EnvirM<EE>) -> RResult<RFunM<T>> {
53        let sym = Symbol::from(x);
54        unsafe { RFunM::new(Rf_findFun(sym.s(), env.s())) }
55    }
56    pub fn ufrom_str_global(x: &str) -> RFunM<T> {
57        let sym = Symbol::from(x);
58        unsafe { RFunM::unew(Rf_findFun(sym.s(), R_GlobalEnv)) }
59    }
60    pub fn ufrom_str<EE: SEXPbucket>(x: &str, env: EnvirM<EE>) -> RFunM<T> {
61        let sym = Symbol::from(x);
62        unsafe { RFunM::unew(Rf_findFun(sym.s(), env.s())) }
63    }
64    pub fn envir<S: SEXPbucket>(&self) -> RResult<EnvirM<S>> {
65        unsafe {
66            if RTYPEOF(self.s()) != CLOSXP {
67                return rraise(format!("not a closure, type = {:?}",
68                                      match_rtype(RTYPEOF(self.s()))));
69            }
70            Ok(EnvirM::from_sexp_envir(CLOENV(self.s())))
71        }
72    }
73    pub fn body(&self) -> SEXP {
74        unsafe { BODY(self.s()) }
75    }
76    pub fn eval<D: RNew>(&self, args: &[&dyn Args]) -> RResult<D> {
77        let call = Shield::new(try!(language1(self, args)));
78        D::rnew(try!(rustr_eval(unsafe { call.s() }, unsafe { R_GlobalEnv })))
79    }
80    pub fn eval_env<EE: SEXPbucket, D: RNew>(&self,
81                                             args: &[&dyn Args],
82                                             envir: EnvirM<EE>)
83                                             -> RResult<D> {
84        let call = Shield::new(try!(language1(self, args)));
85        D::rnew(try!(rustr_eval(unsafe { call.s() }, unsafe { envir.s() })))
86    }
87}
88
89// impl<'a, T: SEXPbucket> From<&'a str> for RFunM<T> {
90//    fn from(x: &'a str) -> RFunM<T> {
91//        RFunM::from_str_global(x)
92//    }
93// }
94
95
96
97
98impl<T: SEXPbucket> RNew for RFunM<T> {
99    fn rnew(x: SEXP) -> RResult<Self> {
100        match unsafe { RTYPEOF(x.s()) } {
101            CLOSXP | SPECIALSXP | BUILTINSXP => Ok(RFunM { data: T::new(unsafe { x.s() }) }),
102            _ => rraise("cannot convert to function"),
103        }
104    }
105}
106
107gen_traits_sexp!(RFunM);