5
5
#define rNull Rcpp::NumericVector (0 )
6
6
template <typename T> Rcpp::IntegerVector SingleInteger(T i) { Rcpp::IntegerVector v (1 ); v[0 ] = i; return v; }
7
7
8
- // RInside RunR::R(0,0,true,false,true);
9
- RInside RunR::R (0 ,0 ,true ,false ,true );
10
-
11
8
class rWrapper { // Wrapper for all my R objects
12
9
public:
13
10
Solver * solver;
@@ -613,48 +610,147 @@ void CLB_WriteConsoleEx( const char* message, int len, int oType ){
613
610
}
614
611
}
615
612
616
- #define R_INTERFACE_PTRS
617
- #include < Rinterface.h>
613
+ #define R_INTERFACE_PTRS
614
+ #include < Rinterface.h>
618
615
619
- int RunR::Init () {
620
- Callback::Init ();
621
- notice (" R: Initializing R environment ..." );
622
616
623
- R[" CLBFunctionCall" ] = Rcpp::InternalFunction ( &CLBFunctionCall );
624
- R[" $.CLB" ] = Rcpp::InternalFunction ( &CLBDollar );
625
- R[" [[.CLB" ] = Rcpp::InternalFunction ( &CLBDollar );
626
- R[" $<-.CLB" ] = Rcpp::InternalFunction ( &CLBDollarAssign );
627
- R[" print.CLB" ] = Rcpp::InternalFunction ( &CLBPrint );
628
- R[" names.CLB" ] = Rcpp::InternalFunction ( &CLBNames );
629
- R.parseEval (" 'CLBFunctionWrap' <- function(obj) { function(...) CLBFunctionCall(obj, list(...)); }" );
617
+ namespace RunR {
618
+ RInside& GetR () {
619
+ static RInside * Rptr;
620
+ if (Rptr == NULL ) {
621
+ notice (" R: Initializing R environment ..." );
622
+ Rptr = new RInside (0 ,0 ,true ,false ,true );
623
+ RInside& R = *Rptr;
624
+
625
+ R[" CLBFunctionCall" ] = Rcpp::InternalFunction ( &CLBFunctionCall );
626
+ R[" $.CLB" ] = Rcpp::InternalFunction ( &CLBDollar );
627
+ R[" [[.CLB" ] = Rcpp::InternalFunction ( &CLBDollar );
628
+ R[" $<-.CLB" ] = Rcpp::InternalFunction ( &CLBDollarAssign );
629
+ R[" [[<-.CLB" ] = Rcpp::InternalFunction ( &CLBDollarAssign );
630
+ R[" print.CLB" ] = Rcpp::InternalFunction ( &CLBPrint );
631
+ R[" names.CLB" ] = Rcpp::InternalFunction ( &CLBNames );
632
+ R.parseEval (" 'CLBFunctionWrap' <- function(obj) { function(...) CLBFunctionCall(obj, list(...)); }" );
633
+ ptr_R_WriteConsoleEx = CLB_WriteConsoleEx ;
634
+ ptr_R_WriteConsole = NULL ;
635
+ R_Outputfile = NULL ;
636
+ R_Consolefile = NULL ;
637
+ R.parseEval (" options(prompt='[ ] R:> ');" );
638
+ }
639
+ return *Rptr;
640
+ };
641
+
642
+ void parseEval (const std::string& source) {
643
+ RInside& R = GetR ();
644
+ R.parseEval (source);
645
+ }
646
+
647
+ int replInit () {
648
+ R_ReplDLLinit ();
649
+ return 0 ;
650
+ }
651
+
652
+ int replDo () {
653
+ return R_ReplDLLdo1 ();
654
+ }
655
+
656
+ SEXP wrap_solver (Solver* solver, vHandler * hand) {
657
+ rWrapper base;
658
+ base.solver = solver;
659
+ base.hand = hand;
660
+ return base.rWrap (new rSolver ());
661
+ }
662
+
663
+ SEXP wrap_handler (Solver* solver, vHandler * hand, const pugi::xml_node& par) {
664
+ rWrapper base;
665
+ base.solver = solver;
666
+ base.hand = hand;
667
+ return base.rWrap (new rXMLNode (par));
668
+ }
669
+ };
630
670
631
- rWrapper base;
632
- base. solver = solver ;
633
- base. hand = this ;
634
- R[ " Solver " ] = base. rWrap ( new rSolver () );
671
+ namespace RunPython {
672
+ bool has_reticulate = false ;
673
+ bool py_initialised = false ;
674
+ void initializePy ( );
635
675
636
- ptr_R_WriteConsoleEx = CLB_WriteConsoleEx ;
637
- ptr_R_WriteConsole = NULL ;
638
- R_Outputfile = NULL ;
639
- R_Consolefile = NULL ;
676
+ void parseEval (const std::string& source) {
677
+ if (! py_initialised) initializePy ();
678
+ Rcpp::Function py_run_string (" py_run_string" );
679
+ py_run_string (source);
680
+ return ;
681
+ }
682
+
683
+ void initializePy () {
684
+ RInside& R = RunR::GetR ();
685
+ has_reticulate = R.parseEval (" require(reticulate, quietly=TRUE)" );
686
+ if (!has_reticulate) throw std::string (" Tried to call Python, but no reticulate installed" );
687
+ py_initialised = true ;
688
+ R.parseEval (
689
+ " py_names = function(obj) names(obj) \n "
690
+ " py_element = function(obj, name) `[[`(obj,name) \n "
691
+ " py_element_assign = function(obj, name, value) `[[<-`(obj,name,value) \n "
692
+ " r_to_py.CLB = function(x, convert=FALSE) py$S3(reticulate:::py_capsule(x))\n "
693
+ );
694
+ parseEval (
695
+ " class S3: \n "
696
+ " def __init__(self, obj): \n "
697
+ " object.__setattr__(self,'obj',obj) \n "
698
+ " def print(self): \n "
699
+ " return r.print(self.obj) \n "
700
+ " def __dir__(self): \n "
701
+ " return r.py_names(self.obj) \n "
702
+ " def __getattr__(self, index): \n "
703
+ " if index.startswith('_'): \n "
704
+ " return None \n "
705
+ " return r.py_element(self.obj, index) \n "
706
+ " def __setattr__(self, index, value): \n "
707
+ " return r.py_element_assign(self.obj, index, value) \n "
708
+ " def __call__(self): \n "
709
+ " raise TypeError('not really callable') \n "
710
+ );
711
+ R.parseEval (
712
+ " py$Solver = r_to_py(Solver)"
713
+ );
714
+ }
715
+
716
+ int replRun () {
717
+ if (! py_initialised) initializePy ();
718
+ Rcpp::Function repl_python (" repl_python" );
719
+ repl_python ();
720
+ return 0 ;
721
+ }
722
+ }
640
723
641
- R.parseEval (" options(prompt='[ ] R:> ');" );
724
+ int cbRunR::Init () {
725
+ Callback::Init ();
726
+ RInside& R = RunR::GetR ();
727
+ R[" Solver" ] = RunR::wrap_solver (solver,this );
642
728
729
+ python = false ;
643
730
interactive = false ;
644
731
echo = true ;
645
732
733
+ std::string name = node.name ();
734
+ if (name == " RunPython" ) python = true ;
646
735
pugi::xml_attribute attr;
647
736
attr = node.attribute (" interactive" );
648
737
if (attr) interactive = attr.as_bool ();
649
738
attr = node.attribute (" echo" );
650
739
if (attr) echo = attr.as_bool ();
651
740
741
+ s_tag++;
742
+ tag = s_tag;
743
+
652
744
source = " " ;
653
- for (pugi::xml_node par = node.first_child (); par; par = par.next_sibling ()) {
745
+ for (pugi::xml_node par = node.first_child (); par; par = par.next_sibling ()) {
654
746
if (par.type () == pugi::node_element) {
747
+ if (python) {
748
+ ERROR (" Code-embedded xml nodes not supported for python" );
749
+ return -1 ;
750
+ }
655
751
char nd_name[20 ];
656
752
sprintf (nd_name, " xml_%0zx" , par.hash_value ());
657
- R[nd_name] = base. rWrap ( new rXMLNode ( par) );
753
+ R[nd_name] = RunR::wrap_handler (solver, this , par);
658
754
659
755
source = source + nd_name + " ()\n " ;
660
756
output (" element\n " );
@@ -668,27 +764,28 @@ int RunR::Init() {
668
764
output (" Unknown\n " );
669
765
}
670
766
}
671
- // output("----- RunR -----\n");
672
- // output("%s\n",source.c_str());
673
- // output("----------------\n");
674
-
767
+ if (echo) {
768
+ output (" -----[ %9s code %03d ]-----\n " , node.name (), tag);
769
+ output (" %s\n " ,source.c_str ());
770
+ output (" --------------------------------\n " );
771
+ }
675
772
return 0 ;
676
773
}
677
774
775
+ int cbRunR::s_tag = 0 ;
678
776
679
- int RunR ::DoIt () {
777
+ int cbRunR ::DoIt () {
680
778
try {
681
779
if (source != " " ) {
682
- solver-> print ( " Running R ... " );
683
- if (echo ) {
684
- output ( " ----- RunR ----- \n " );
685
- output ( " %s \n " ,source. c_str ());
686
- output ( " ---------------- \n " );
780
+ output ( " %8d it Executing %s code %03d \n " , solver-> iter , node. name (), tag );
781
+ if (python ) {
782
+ RunPython::parseEval (source );
783
+ } else {
784
+ RunR::parseEval (source );
687
785
}
688
- R.parseEval (source);
689
786
}
690
787
if (!interactive) {
691
- if (echo) NOTICE (" You can run interactive R session with Ctrl+X" );
788
+ if (echo) NOTICE (" You can run interactive %s session with Ctrl+X" , node. name () );
692
789
int c = kbhit ();
693
790
if (c == 24 ) {
694
791
int a = getchar ();
@@ -698,10 +795,21 @@ int RunR::DoIt() {
698
795
}
699
796
}
700
797
if (interactive) {
701
- R_ReplDLLinit ();
702
- while ( R_ReplDLLdo1 () > 0 ) {}
798
+ if (python) {
799
+ RunPython::replRun ();
800
+ } else {
801
+ RunR::replInit ();
802
+ while ( RunR::replDo () > 0 ) {}
803
+ }
703
804
}
805
+ } catch (Rcpp::exception & ex) {
806
+ ERROR (" Caught Rcpp exception" );
807
+ return -1 ;
808
+ } catch (std::exception &ex) {
809
+ ERROR (" Caught std exception: %s" , ex.what ());
810
+ return -1 ;
704
811
} catch (...) {
812
+ ERROR (" Caught uknown exception" );
705
813
return -1 ;
706
814
}
707
815
return 0 ;
@@ -713,9 +821,9 @@ int RunR::DoIt() {
713
821
// Function created only to check to create Handler for specific conditions
714
822
vHandler * Ask_For_RunR (const pugi::xml_node& node) {
715
823
std::string name = node.name ();
716
- if (name == " RunR" ) {
824
+ if (name == " RunR" || name == " RunPython " ) {
717
825
#ifdef WITH_R
718
- return new RunR ;
826
+ return new cbRunR ;
719
827
#else
720
828
ERROR (" No R support. configure with --enable-rinside\n " );
721
829
exit (-1 );
0 commit comments