Inferno  0.2
soft_patterns.hpp
Go to the documentation of this file.
00001 #ifndef SOFT_PATTERNS_HPP
00002 #define SOFT_PATTERNS_HPP
00003 
00004 #include "search_replace.hpp"
00005 #include "helpers/transformation.hpp"
00006 
00007 
00008 struct NotMatchBase {}; // needed for graph plotter
00009 
00010 // Match if the supplied patterns does not match (between you and me, it's just a NOT)
00011 template<class PRE_RESTRICTION>
00012 struct NotMatch : Special<PRE_RESTRICTION>,
00013                  SoftSearchPattern,
00014                  NotMatchBase,
00015                  CouplingSlave
00016 {
00017   SPECIAL_NODE_FUNCTIONS
00018   // Pattern is an abnormal context. Fascinatingly, we can supply any node here because there
00019     // is no type-correctness limitation with *excluding* a kind of node
00020     TreePtr<Node> pattern;
00021     CompareReplace comp; // TODO only want the Compare
00022 private:
00023     virtual bool DecidedCompare( const CompareReplace *sr,
00024                                const TreePtrInterface &x,
00025                                bool can_key,
00026                                Conjecture &conj ) 
00027     {
00028         INDENT("!");
00029         ASSERT( pattern );
00030       if( can_key )
00031       {
00032         // Don't do a subtree search while keying - we'll only end up keying the wrong thing
00033         // or terminating with false prematurely
00034         return true;
00035       }
00036       else
00037       {
00038           // Do not use the present conjecture since we would mess it up because
00039           // a. We didn't recurse during KEYING pass and
00040           // b. Search under not can terminate with false, but parent search will continue
00041           // Consequently, we go in at Compare level, which creates a new conjecture.
00042           comp.pcontext = sr->pcontext;
00043         bool r = comp.Compare( x, pattern, true );
00044       TRACE("NotMatch pattern=")(*pattern)(" x=")(*x)(" got %d, returning the opposite!\n", (int)r);
00045         if( r==false )
00046         return true;
00047       else
00048         return false;
00049       }
00050     }
00051     virtual void SetCouplingsMaster( CouplingKeys *ck )
00052     {
00053         comp.coupling_keys.SetMaster( ck ); 
00054     }
00055 };
00056 
00057 struct MatchAllBase : virtual Node
00058 {
00059     virtual CollectionInterface &GetPatterns() = 0;
00060 };
00061 
00062 // Match all of the supplied patterns (between you and me, it's an AND)
00063 template<class PRE_RESTRICTION>
00064 struct MatchAll : Special<PRE_RESTRICTION>,
00065                  SoftSearchPattern,
00066                  SoftReplacePattern, 
00067                  MatchAllBase
00068 {
00069   SPECIAL_NODE_FUNCTIONS
00070     mutable Collection<PRE_RESTRICTION> patterns; // TODO provide const iterators and remove mutable
00071     MatchAll() : initialised( false ) {}
00072 private:
00073     mutable bool initialised;
00074     mutable TreePtr<Node> modifier_pattern;
00075     virtual bool DecidedCompare( const CompareReplace *sr,
00076                                    const TreePtrInterface &x,
00077                                    bool can_key,
00078                                    Conjecture &conj ) 
00079     {
00080         INDENT("&");
00081       FOREACH( const TreePtr<PRE_RESTRICTION> i, patterns )
00082       {
00083           ASSERT( i );
00084         bool r = sr->DecidedCompare( x, TreePtr<Node>(i), can_key, conj );
00085           if( !r )
00086             return false;
00087       }
00088         return true;
00089     }
00090 
00091     virtual TreePtr<Node> DuplicateSubtree( const CompareReplace *sr )
00092     {
00093         return TreePtr<Node>();
00094         //ASSERTFAIL("MatchAll in replace - it should be coupled because it should be in the search pattern\n");
00095     }
00096 
00097     void EnsureInitialised()
00098     {
00099         if( initialised )
00100             return;
00101     
00102         // MatchAll can appear in replace path; if so, see whether any patterns contain
00103         // modifiers, which change the tree relative to the present coupling. If so, 
00104         // overlay that over the coupling. There must not be more than one modifier, 
00105         // because behaviour would be indeterminate (patterns are unordered).
00106         //TRACE("Coupled MatchAll: dest=")(*dest)("\n");
00107         // TODO can we not arrange for the replace path to go directly to the desired child?
00108         // maybe by inserting an Overlay? Then we could make MatchAll be search-only
00109 
00110         FOREACH( TreePtr<Node> source_pattern, GetPatterns() )
00111         {                
00112             Walk e(source_pattern);
00113             FOREACH( TreePtr<Node> n, e )
00114             {
00115                 if( dynamic_pointer_cast<SoftReplacePattern>(n) || 
00116                     dynamic_pointer_cast<OverlayBase>(n) ||
00117                     dynamic_pointer_cast<SlaveBase>(n) ) // TODO common base class for these called Modifier
00118                 {
00119                     ASSERT( !modifier_pattern )("MatchAll coupled into replace must have no more than one modifying pattern:")
00120                           (" first saw ")(*modifier_pattern)(" and now got ")(*n)("\n");   
00121                     modifier_pattern = source_pattern;
00122                     break;
00123                 }
00124             }                     
00125         }
00126         initialised = true;
00127     }
00128 
00129     virtual TreePtr<Node> GetOverlayPattern()
00130     {
00131         EnsureInitialised();
00132         return modifier_pattern;
00133     } 
00134     
00135     CollectionInterface &GetPatterns() { return patterns; } // TODO try covariant?
00136 };
00137 
00138 struct MatchAnyBase {};
00139 
00140 // Match zero or more of the supplied patterns (between you and me, it's an OR)
00141 template<class PRE_RESTRICTION>
00142 struct MatchAny : Special<PRE_RESTRICTION>,
00143                  SoftSearchPattern,
00144                  MatchAnyBase
00145 {
00146   SPECIAL_NODE_FUNCTIONS
00147   // Patterns are an abnormal context
00148     mutable Collection<PRE_RESTRICTION> patterns; // TODO provide const iterators and remove mutable
00149 private:
00150     virtual bool DecidedCompare( const CompareReplace *sr,
00151                                const TreePtrInterface &x,
00152                                bool can_key,
00153                                Conjecture &conj ) 
00154     {
00155         INDENT("|");
00156       FOREACH( const TreePtr<PRE_RESTRICTION> i, patterns )
00157       {
00158           ASSERT( i );
00159         bool r = sr->Compare( x, i, false );
00160           if( r )
00161             return true;
00162       }
00163         return false;
00164     }
00165 };
00166 
00167 
00168 struct MatchOddBase {};
00169 
00170 // Match an odd number of patterns (between you and me, it's an EOR)
00171 template<class PRE_RESTRICTION>
00172 struct MatchOdd : Special<PRE_RESTRICTION>,
00173                   SoftSearchPattern,
00174                   MatchOddBase
00175 {
00176   SPECIAL_NODE_FUNCTIONS
00177     mutable Collection<PRE_RESTRICTION> patterns; // TODO provide const iterators and remove mutable
00178 private:
00179     virtual bool DecidedCompare( const CompareReplace *sr,
00180                                const TreePtrInterface &x,
00181                                bool can_key,
00182                                Conjecture &conj ) 
00183     {
00184         INDENT("^");
00185       int tot=0;
00186       FOREACH( const TreePtr<PRE_RESTRICTION> i, patterns )
00187       {
00188           ASSERT( i );
00189           bool r = sr->Compare( x, i, false );
00190           if( r )
00191             tot++;
00192       }
00193         return (tot%2) ? true : false;
00194     }
00195 };
00196 
00197 
00198 struct TransformOfBase : SoftSearchPatternSpecialKey,
00199                          TerminusBase
00200 {
00201     TreePtr<Node> pattern; 
00202     Transformation *transformation;
00203     TransformOfBase( Transformation *t, TreePtr<Node> p=TreePtr<Node>() ) :
00204       transformation(t),
00205       pattern(p)
00206     {
00207     }
00208 
00209 private:
00210     virtual shared_ptr<Key> DecidedCompare( const CompareReplace *sr,
00211                              const TreePtrInterface &x,
00212                              bool can_key,
00213                              Conjecture &conj );
00214 protected: 
00215     TransformOfBase() {}    
00216 };
00217 
00218 template<class PRE_RESTRICTION>
00219 struct TransformOf : TransformOfBase, Special<PRE_RESTRICTION>
00220 {
00221   SPECIAL_NODE_FUNCTIONS  
00222     TransformOf() {}    
00223     TransformOf( Transformation *t, TreePtr<Node> p=TreePtr<Node>() ) : 
00224         TransformOfBase(t, p) 
00225     {
00226     }
00227 };
00228 
00229 
00230 struct PointerIsBase
00231 {
00232 };
00233 /** Make an architype of the pointed-to type and compare that.
00234     So if in the program tree we have a->b and the search pattern is
00235     x->PointerIsBase->y, then a must match x, and the type of the pointer
00236     in a that points to b must match y. */
00237 template<class PRE_RESTRICTION>
00238 struct PointerIs : Special<PRE_RESTRICTION>,
00239                    SoftSearchPattern,
00240                    PointerIsBase // TODO document
00241 {
00242     SPECIAL_NODE_FUNCTIONS
00243     TreePtr<PRE_RESTRICTION> pointer;
00244     virtual bool DecidedCompare( const CompareReplace *sr,
00245                                    const TreePtrInterface &x,
00246                                    bool can_key,
00247                                    Conjecture &conj ) 
00248     {
00249         INDENT("@");
00250         
00251         TreePtr<Node> ptr_arch = x.MakeValueArchitype();
00252         
00253         return sr->DecidedCompare( ptr_arch, pointer, can_key, conj );
00254     }
00255 };
00256 
00257 #endif