Inferno  0.2
transformation.hpp
Go to the documentation of this file.
00001 #ifndef TRANSFORMATION_HPP
00002 #define TRANSFORMATION_HPP
00003 
00004 #include "node/node.hpp"
00005 #include "common/trace.hpp"
00006 
00007 // TODO For in-place, use (*pcontext, *proot) rather than (context, *root). This 
00008 // way the caller has to decide whether the context node is the same as the root node, 
00009 // or some ancestor. If proot==pcontext, then writes through proot will magically 
00010 // become visible through pcontext. If they differ, assume *proot is under *pcontext, 
00011 // and therefore *pcontext does not need to change. Add an assert somewhere that 
00012 // *proot is indeed somewhere under *pcontext (or they are the same).
00013 // Then remove the if( context == *proot ) checks from TransformationVector
00014 // and CompareReplace. Really, this TODO is just to use these two local 
00015 // policies as the general policy.
00016 
00017 class Transformation : public Traceable
00018 {
00019 public:
00020     // Apply this transformation to tree at root, using context for decls etc.
00021   // Out-of-place version, neither context nor tree may be modified.
00022     virtual TreePtr<Node> operator()( TreePtr<Node> context,       // The whole program, so declarations may be searched for
00023                                     TreePtr<Node> root ) = 0;   // Root of the subtree we want to modify
00024 
00025     inline TreePtr<Node> operator()( TreePtr<Node> root )
00026     {
00027       return operator()( root, root );
00028     }
00029 
00030     // Apply this transformation to tree at *proot, using context for decls etc.
00031   // In-place version, node at proot will be updated to the new tree.
00032     virtual void operator()( TreePtr<Node> context,         // The whole program, so declarations may be searched for
00033                          TreePtr<Node> *proot ) = 0;    // Root of the subtree we want to modify
00034 
00035     inline void operator()( TreePtr<Node> *proot )
00036     {
00037       operator()( *proot, proot );
00038     }
00039     
00040     // Provide information for the graph plotter, so it can draw the tx as a node
00041     // with 0 or more links to TreePtrs
00042     virtual void GetGraphInfo( vector<string> *labels, 
00043                                vector< TreePtr<Node> > *links ) const 
00044     {
00045     }
00046 };
00047 
00048 
00049 class InPlaceTransformation : public Transformation
00050 {
00051 public:
00052   using Transformation::operator();
00053 
00054   // Implement out-of-place in terms of in-place
00055     virtual TreePtr<Node> operator()( TreePtr<Node> context,
00056                                         TreePtr<Node> root )
00057     {
00058         ASSERTFAIL("TODO copy subtree");
00059     }                                    
00060 };
00061 
00062 
00063 class OutOfPlaceTransformation : public Transformation
00064 {
00065 public:
00066   using Transformation::operator();
00067 
00068     // Implement in-place in terms of out-of-place
00069     virtual void operator()( TreePtr<Node> context,
00070                          TreePtr<Node> *proot )
00071     {
00072         TreePtr<Node> result_root = operator()( context, *proot );
00073         *proot = result_root;
00074     }                                    
00075 };
00076 
00077 class TransformationVector : public vector< shared_ptr<Transformation> >,
00078                              public InPlaceTransformation
00079 {
00080     virtual void operator()( TreePtr<Node> context,     // The whole program, so declarations may be searched for
00081                          TreePtr<Node> *proot )     // Root of the subtree we want to modify
00082     {
00083         TreePtr<Node> *pcontext;
00084         if( context = *proot )
00085             pcontext = proot;
00086         else 
00087             pcontext = &context;
00088         FOREACH( shared_ptr<Transformation> t, *this )
00089             (*t)(*pcontext, proot);
00090     }                              
00091 };
00092 
00093 
00094 
00095 class Filter
00096 {
00097 public:
00098     // Test the subtree at the supplied root, producing true or false
00099     virtual bool IsMatch( TreePtr<Node> context,       // The whole program, so declarations may be searched for
00100                           TreePtr<Node> root ) = 0;   // Root of the subtree we want to test
00101 
00102     inline bool IsMatch( TreePtr<Node> root )
00103     {
00104         return IsMatch( root, root );
00105     }
00106 };
00107 
00108 
00109 #endif