1 #ifndef SOURCETOOLS_R_R_CALL_RECURSER_H
2 #define SOURCETOOLS_R_R_CALL_RECURSER_H
3 
4 #include <vector>
5 
6 #include <sourcetools/core/core.h>
7 
8 #include <sourcetools/r/RHeaders.h>
9 #include <sourcetools/r/RFunctions.h>
10 
11 
12 namespace sourcetools {
13 namespace r {
14 
15 class CallRecurser : noncopyable
16 {
17 public:
18 
19   class Operation
20   {
21   public:
22     virtual void apply(SEXP dataSEXP) = 0;
~Operation()23     virtual ~Operation() {}
24   };
25 
CallRecurser(SEXP dataSEXP)26   explicit CallRecurser(SEXP dataSEXP)
27   {
28     if (Rf_isPrimitive(dataSEXP))
29       dataSEXP_ = R_NilValue;
30     else if (Rf_isFunction(dataSEXP))
31       dataSEXP_ = r::util::functionBody(dataSEXP);
32     else if (TYPEOF(dataSEXP) == LANGSXP)
33       dataSEXP_ = dataSEXP;
34     else
35       dataSEXP_ = R_NilValue;
36   }
37 
add(Operation * pOperation)38   void add(Operation* pOperation)
39   {
40     operations_.push_back(pOperation);
41   }
42 
run()43   void run()
44   {
45     runImpl(dataSEXP_);
46   }
47 
runImpl(SEXP dataSEXP)48   void runImpl(SEXP dataSEXP)
49   {
50     for (std::vector<Operation*>::iterator it = operations_.begin();
51          it != operations_.end();
52          ++it)
53     {
54       (*it)->apply(dataSEXP);
55     }
56 
57     if (TYPEOF(dataSEXP) == LANGSXP)
58     {
59       while (dataSEXP != R_NilValue)
60       {
61         runImpl(CAR(dataSEXP));
62         dataSEXP = CDR(dataSEXP);
63       }
64     }
65   }
66 
67 private:
68   SEXP dataSEXP_;
69   std::vector<Operation*> operations_;
70 };
71 
72 } // namespace r
73 } // namespace sourcetools
74 
75 #endif /* SOURCETOOLS_R_R_CALL_RECURSER_H */
76