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