Inferno
0.2
|
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