Rcpp Version 0.9.10
Environment.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 //
00003 // Environment.cpp: Rcpp R/C++ interface class library -- Environments
00004 //
00005 // Copyright (C) 2009 - 2011 Dirk Eddelbuettel and Romain Francois
00006 //
00007 // This file is part of Rcpp.
00008 //
00009 // Rcpp is free software: you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 2 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // Rcpp is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022 #include <Rcpp/Environment.h>
00023 
00024 namespace Rcpp {
00025 
00026     Environment::Environment() : RObject(R_NilValue){}
00027 
00028     Environment::Environment( SEXP x = R_GlobalEnv) : RObject(x){
00029         if( ! Rf_isEnvironment(x) ) {
00030             /* not an environment, but maybe convertible to one using as.environment, try that */
00031             SEXP res ;
00032             try {
00033                 SEXP asEnvironmentSym = Rf_install("as.environment"); // cannot be gc()'ed  once in symbol table
00034                 res = Evaluator::run( Rf_lang2(asEnvironmentSym, x ) ) ;
00035             } catch( const eval_error& ex){
00036                 throw not_compatible( "cannot convert to environment"  ) ; 
00037             }
00038             setSEXP( res ) ;
00039         }
00040     }
00041 
00042     Environment::Environment( const std::string& name) : RObject(R_EmptyEnv){
00043         /* similar to matchEnvir@envir.c */
00044         if( name == ".GlobalEnv" ) {
00045             setSEXP( R_GlobalEnv ) ;
00046         } else if( name == "package:base" ){
00047             setSEXP( R_BaseEnv ) ;
00048         } else{
00049             SEXP res = R_NilValue ;
00050             try{
00051                 SEXP asEnvironmentSym = Rf_install("as.environment"); // cannot be gc()'ed  once in symbol table
00052                 res = Evaluator::run(Rf_lang2( asEnvironmentSym, Rf_mkString(name.c_str()) ) ) ;
00053             } catch( const eval_error& ex){
00054                 throw no_such_env(name) ;
00055             }
00056             setSEXP( res ) ;
00057         }
00058     }
00059     
00060     Environment::Environment(int pos) : RObject(R_GlobalEnv){
00061         SEXP res ;
00062         try{
00063             SEXP asEnvironmentSym = Rf_install("as.environment"); // cannot be gc()'ed  once in symbol table
00064             res =  Evaluator::run( Rf_lang2( asEnvironmentSym, Rf_ScalarInteger(pos) ) ) ;
00065         } catch( const eval_error& ex){
00066             throw no_such_env(pos) ;
00067         }
00068         setSEXP( res ) ;
00069     }
00070     
00071     Environment::Environment( const Environment& other ) {
00072         setSEXP( other.asSexp() ) ; 
00073     }
00074     
00075     Environment& Environment::operator=(const Environment& other) {
00076         setSEXP( other.asSexp() ) ; 
00077         return *this ;
00078     }
00079     
00080     Environment::~Environment(){
00081         logTxt( "~Environment" ) ;
00082     }
00083         
00084     SEXP Environment::ls( bool all = true) const {
00085         if( is_user_database() ){
00086             R_ObjectTable *tb = (R_ObjectTable*)
00087                 R_ExternalPtrAddr(HASHTAB(m_sexp));
00088             return tb->objects(tb) ;
00089         } else{
00090             Rboolean get_all = all ? TRUE : FALSE ;
00091             return R_lsInternal( m_sexp, get_all ) ;
00092         }
00093         return R_NilValue ;
00094     }
00095     
00096     SEXP Environment::get( const std::string& name) const {
00097         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00098         SEXP res = Rf_findVarInFrame( m_sexp, nameSym ) ;
00099         
00100         if( res == R_UnboundValue ) return R_NilValue ;
00101         
00102         /* We need to evaluate if it is a promise */
00103         if( TYPEOF(res) == PROMSXP){
00104             res = Rf_eval( res, m_sexp ) ;
00105         }
00106         return res ;
00107     }
00108     
00109     SEXP Environment::find( const std::string& name) const {
00110         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00111         SEXP res = Rf_findVar( nameSym, m_sexp ) ;
00112         
00113         if( res == R_UnboundValue ) throw binding_not_found(name) ;
00114         
00115         /* We need to evaluate if it is a promise */
00116         if( TYPEOF(res) == PROMSXP){
00117             res = Rf_eval( res, m_sexp ) ;
00118         }
00119         return res ;
00120     }
00121     
00122     bool Environment::exists( const std::string& name) const{
00123         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00124         SEXP res = Rf_findVarInFrame( m_sexp, nameSym  ) ;
00125         return res != R_UnboundValue ;
00126     }
00127     
00128     bool Environment::assign( const std::string& name, SEXP x = R_NilValue) const {
00129         if( exists( name) && bindingIsLocked(name) ) throw binding_is_locked(name) ;
00130         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00131         Rf_defineVar( nameSym, x, m_sexp );
00132         return true ;
00133     }
00134     
00135     bool Environment::remove( const std::string& name) {
00136         if( exists(name) ){
00137             if( bindingIsLocked(name) ){
00138                 throw binding_is_locked(name) ;
00139             } else{
00140                 /* unless we want to copy all of do_remove, 
00141                    we have to go back to R to do this operation */
00142                 SEXP internalSym = Rf_install( ".Internal" );
00143                 SEXP removeSym = Rf_install( "remove" );
00144                 SEXP call = PROTECT( Rf_lang2(internalSym, Rf_lang4(removeSym, Rf_mkString(name.c_str()), 
00145                                                                     m_sexp, Rf_ScalarLogical( FALSE ))) );
00146                 Rf_eval( call, R_GlobalEnv ) ;
00147                 UNPROTECT(1) ;
00148             }
00149         } else{
00150             throw no_such_binding(name) ;
00151         }
00152         return true; // to make g++ -Wall happy
00153     }
00154     
00155     bool Environment::isLocked() const{
00156         return R_EnvironmentIsLocked(m_sexp);
00157     }
00158     
00159     bool Environment::bindingIsActive(const std::string& name) const {
00160         if( !exists( name) ) throw no_such_binding(name) ;
00161         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00162         return R_BindingIsActive(nameSym, m_sexp) ;
00163     }
00164     
00165     bool Environment::bindingIsLocked(const std::string& name) const {
00166         if( !exists( name) ) throw no_such_binding(name) ;
00167         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00168         return R_BindingIsLocked(nameSym, m_sexp) ;
00169     }
00170     
00171     void Environment::lock( bool bindings = false ) {
00172         R_LockEnvironment( m_sexp, bindings ? TRUE: FALSE ) ;
00173     }
00174     
00175     void Environment::lockBinding(const std::string& name) {
00176         if( !exists( name) ) throw no_such_binding(name) ;
00177         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00178         R_LockBinding( nameSym, m_sexp ); 
00179     }
00180     
00181     void Environment::unlockBinding(const std::string& name) {
00182         if( !exists( name) ) throw no_such_binding(name) ;
00183         SEXP nameSym = Rf_install(name.c_str());        // cannot be gc()'ed  once in symbol table
00184         R_unLockBinding( nameSym, m_sexp );
00185     }
00186     
00187     bool Environment::is_user_database() const {
00188         return OBJECT(m_sexp) && Rf_inherits(m_sexp, "UserDefinedDatabase") ;
00189     }
00190     
00191     /* static */
00192     
00193     Environment Environment::global_env() {
00194         return Environment(R_GlobalEnv) ;
00195     }
00196     
00197     Environment Environment::empty_env() {
00198         return Environment(R_EmptyEnv) ;
00199     }
00200     
00201     Environment Environment::base_env() {
00202         return Environment(R_BaseEnv) ;
00203     }
00204     
00205     Environment Environment::base_namespace() {
00206         return Environment(R_BaseNamespace) ;
00207     }
00208     
00209     Environment Environment::namespace_env(const std::string& package) {
00210         
00211         SEXP env = R_NilValue ;
00212         try{
00213             SEXP getNamespaceSym = Rf_install("getNamespace");
00214             env = Evaluator::run( Rf_lang2(getNamespaceSym, Rf_mkString(package.c_str()) ) ) ;
00215         } catch( const eval_error& ex){
00216             throw no_such_namespace( package  ) ; 
00217         }
00218         return Environment( env ) ;
00219     }
00220     
00221     Environment Environment::parent() const {
00222         return Environment( ENCLOS(m_sexp) ) ; 
00223     }
00224     
00225     Environment::Binding::Binding( Environment& env_, const std::string& name_): 
00226         env(env_), name(name_){}
00227     
00228     bool Environment::Binding::active() const{
00229         return env.bindingIsActive( name ) ; 
00230     }
00231     
00232     bool Environment::Binding::exists() const{
00233         return env.exists( name ) ; 
00234     }
00235     
00236     bool Environment::Binding::locked() const{
00237         return env.bindingIsLocked( name ) ; 
00238     }
00239     
00240     void Environment::Binding::lock() {
00241         env.lockBinding( name ) ;
00242     }
00243     
00244     void Environment::Binding::unlock() {
00245         env.unlockBinding( name ) ;
00246     }
00247     
00248     Environment::Binding& Environment::Binding::operator=( SEXP rhs ){
00249         env.assign( name, rhs ) ;
00250         return *this ;
00251     }
00252     
00253     Environment::Binding& Environment::Binding::operator=( const Binding& rhs){
00254         env.assign( name, rhs.env.get(rhs.name) ) ;
00255         return *this ;
00256     }
00257 
00258     const Environment::Binding Environment::operator[]( const std::string& name) const{
00259         return Binding( const_cast<Environment&>(*this), name );
00260     }
00261     
00262     Environment::Binding Environment::operator[]( const std::string& name) {
00263         return Binding( *this, name ) ;
00264     }
00265     
00266     Environment Environment::Rcpp_namespace() {
00267         return Rcpp::internal::get_Rcpp_namespace() ;
00268     }
00269     
00270     Environment Environment::new_child(bool hashed) {
00271         SEXP newEnvSym = Rf_install("new.env");
00272         return Environment( Evaluator::run(Rf_lang3( newEnvSym, Rf_ScalarLogical(hashed), m_sexp )) );
00273     }
00274     
00275     
00276 } // namespace Rcpp
00277 
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines