1 ///////////////////////////////////////////////////////////////////////////////
2 // This file is generated automatically using Prop (version 2.3.6),
3 // last updated on Nov 2, 1999.
4 // The original source file is "indexing.pcc".
5 ///////////////////////////////////////////////////////////////////////////////
8 ///////////////////////////////////////////////////////////////////////////////
9 // Indexing optimizations for pattern matching.
11 // The following indexing schemes is largely inspired by the work of
12 // Sekar, Ramesh and Ramakrishnan in ``Adaptive Pattern Matching.''
13 // Techreport, SUNY at Stony Brook (year 91+ but unknown).
15 // Intuitively, an index is the next position of a pattern that must be
16 // inspected to determine a match(Levy and Huet). Given a set of
17 // prioritized patterns, at least an index must exist at each position.
18 // The algorithm of SRR attempts to locate the index at each position
19 // when constructing the the DFA-like matching automata.
21 // In the previous algorithm I've implemented, merging of matching trees at
22 // identical positions are performed and the resulting automaton guarantees
23 // that the same position is only examined once. This is an improvement
24 // over Wadler's algorithm, which may examine the same position more than
25 // once in a match. However, we may examine a position even if it is not
34 // We exam position 1, 2, 3 in sequence in term f even though it is
35 // best to exam position 2 first.
37 // I think my algorithm is similar to the one by Graf. In any case,
38 // My, Graf's and Wadler's algorithms all use a fixed traversal order
39 // (usually left-to-right). However, the intuition is that in many instances
40 // it is best if the traversal order *adapts* itself according to the
41 // pattern. This is the essential idea of SRR's algorithm.
43 // Sekar et al. have shown that constructing a DFA-like matching
44 // automata can be exponential in time and space. They have
45 // developed a polynomial time algorithm for computing indices for untyped
46 // terms. Unfortunately, in our typed case the time complexity of index
47 // computation is co-NP.
49 // So we'll just use a few heuristics to compute something close to
50 // the notion of an index, and cross our fingers and hope for the best.
51 ///////////////////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////////////////
59 // Hash function on position list
61 ///////////////////////////////////////////////////////////////////////////////
62 unsigned int pos_hash (HashTable::Key p
)
66 #line 58 "indexing.pcc"
67 #line 63 "indexing.pcc"
71 switch (untagp(pos
)) {
72 case a_Pos::tag_POSint
: {
73 #line 61 "indexing.pcc"
74 h
+= ((Pos_POSint
*)pos
)->_1
; pos
= ((Pos_POSint
*)pos
)->_2
;
75 #line 61 "indexing.pcc"
77 case a_Pos::tag_POSlabel
: {
78 #line 62 "indexing.pcc"
79 h
+= (unsigned int)((Pos_POSlabel
*)derefp(pos
))->_1
; pos
= ((Pos_POSlabel
*)derefp(pos
))->_2
;
80 #line 62 "indexing.pcc"
83 #line 63 "indexing.pcc"
84 h
+= ((Pos_POSadaptive
*)derefp(pos
))->_1
+ 437; pos
= ((Pos_POSadaptive
*)derefp(pos
))->_3
;
85 #line 63 "indexing.pcc"
91 #line 60 "indexing.pcc"
93 #line 60 "indexing.pcc"
96 #line 59 "indexing.pcc"
98 #line 59 "indexing.pcc"
103 #line 64 "indexing.pcc"
104 #line 64 "indexing.pcc"
108 ///////////////////////////////////////////////////////////////////////////////
110 // Checks if a pattern is refutable.
112 ///////////////////////////////////////////////////////////////////////////////
113 Bool
is_refutable(Pat pat
)
115 #line 73 "indexing.pcc"
116 #line 98 "indexing.pcc"
120 switch (pat
->tag__
) {
121 case a_Pat::tag_WILDpat
: {
123 #line 74 "indexing.pcc"
125 #line 74 "indexing.pcc"
127 case a_Pat::tag_IDpat
: {
128 if (((Pat_IDpat
*)pat
)->_3
) {
130 #line 76 "indexing.pcc"
132 #line 76 "indexing.pcc"
135 case a_Pat::tag_CONSpat
: {
136 if (((Pat_CONSpat
*)pat
)->CONSpat
) {
137 if (((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
) {
138 switch (((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
->tag__
) {
139 case a_Ty::tag_TYCONty
: {
140 if (boxed(((Ty_TYCONty
*)((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
)->_1
)) {
141 switch (((Ty_TYCONty
*)((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
)->_1
->tag__
) {
142 case a_TyCon::tag_DATATYPEtycon
: {
143 #line 92 "indexing.pcc"
144 return ((((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
)->_1
)->unit
+ ((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
)->_1
)->arg
> 1) || (((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)((Pat_CONSpat
*)pat
)->CONSpat
->alg_ty
)->_1
)->qualifiers
& QUALextensible
));
145 #line 92 "indexing.pcc"
149 #line 98 "indexing.pcc"
150 bug("is_refutable()");
151 #line 98 "indexing.pcc"
156 default: { goto L5
; } break;
161 case a_Pat::tag_APPpat
: {
162 #line 93 "indexing.pcc"
163 return is_refutable(((Pat_APPpat
*)pat
)->_1
) || is_refutable(((Pat_APPpat
*)pat
)->_2
);
164 #line 93 "indexing.pcc"
166 case a_Pat::tag_TYPEDpat
: {
167 #line 78 "indexing.pcc"
168 pat
= ((Pat_TYPEDpat
*)pat
)->_1
;
169 #line 78 "indexing.pcc"
171 case a_Pat::tag_ASpat
: {
172 if (((Pat_ASpat
*)pat
)->_4
) { goto L4
; } else {
173 #line 77 "indexing.pcc"
174 pat
= ((Pat_ASpat
*)pat
)->_2
;
175 #line 77 "indexing.pcc"
178 case a_Pat::tag_CONTEXTpat
: {
179 #line 86 "indexing.pcc"
180 return is_refutable(((Pat_CONTEXTpat
*)pat
)->_2
);
181 #line 86 "indexing.pcc"
183 case a_Pat::tag_ARRAYpat
: {
184 #line 82 "indexing.pcc"
185 return is_refutable(((Pat_ARRAYpat
*)pat
)->_1
);
186 #line 82 "indexing.pcc"
188 case a_Pat::tag_TUPLEpat
: {
189 #line 81 "indexing.pcc"
190 return is_refutable(((Pat_TUPLEpat
*)pat
)->TUPLEpat
);
191 #line 81 "indexing.pcc"
193 case a_Pat::tag_RECORDpat
: {
194 #line 85 "indexing.pcc"
195 return is_refutable(((Pat_RECORDpat
*)pat
)->_1
);
196 #line 85 "indexing.pcc"
198 case a_Pat::tag_LISTpat
: {
199 #line 95 "indexing.pcc"
200 if (is_refutable(((Pat_LISTpat
*)pat
)->head
)) return true;
201 pat
= ((Pat_LISTpat
*)pat
)->tail
;
203 #line 97 "indexing.pcc"
205 case a_Pat::tag_VECTORpat
: {
206 #line 84 "indexing.pcc"
207 return is_refutable(((Pat_VECTORpat
*)pat
)->len
) || is_refutable(((Pat_VECTORpat
*)pat
)->elements
);
208 #line 84 "indexing.pcc"
210 case a_Pat::tag_LOGICALpat
: {
211 #line 80 "indexing.pcc"
212 return is_refutable(((Pat_LOGICALpat
*)pat
)->_2
) || is_refutable(((Pat_LOGICALpat
*)pat
)->_3
);
213 #line 80 "indexing.pcc"
215 case a_Pat::tag_MARKEDpat
: {
216 #line 79 "indexing.pcc"
217 pat
= ((Pat_MARKEDpat
*)pat
)->_2
;
218 #line 79 "indexing.pcc"
220 case a_Pat::tag_LITERALpat
:
221 case a_Pat::tag_LEXEMEpat
: { goto L4
; } break;
222 default: { goto L5
; } break;
227 #line 99 "indexing.pcc"
228 #line 99 "indexing.pcc"
232 ///////////////////////////////////////////////////////////////////////////////
234 // Is a pattern list refutable?
236 ///////////////////////////////////////////////////////////////////////////////
237 Bool
is_refutable(Pats pats
)
238 { for_each (Pat
, p
, pats
) if (is_refutable(p
)) return true;
242 ///////////////////////////////////////////////////////////////////////////////
244 // Is a labeled pattern list refutable?
246 ///////////////////////////////////////////////////////////////////////////////
247 Bool
is_refutable(LabPats pats
)
248 { for_each (LabPat
, p
, pats
) if (is_refutable(p
.pat
)) return true;
252 ///////////////////////////////////////////////////////////////////////////////
254 // Method to compute the indices.
256 ///////////////////////////////////////////////////////////////////////////////
257 void indexing(int priority
, Pat pat
, Pos pos
, HashTable
& index_map
)
259 #line 128 "indexing.pcc"
260 #line 146 "indexing.pcc"
264 switch (pat
->tag__
) {
265 case a_Pat::tag_APPpat
: {
266 if (((Pat_APPpat
*)pat
)->_1
) {
267 switch (((Pat_APPpat
*)pat
)->_1
->tag__
) {
268 case a_Pat::tag_CONSpat
: {
269 if (((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
) {
270 if (((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->alg_ty
) {
271 switch (((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->alg_ty
->tag__
) {
272 case a_Ty::tag_TYCONty
: {
273 if (boxed(((Ty_TYCONty
*)((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->alg_ty
)->_1
)) {
274 switch (((Ty_TYCONty
*)((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->alg_ty
)->_1
->tag__
) {
275 case a_TyCon::tag_DATATYPEtycon
: {
276 if (((Pat_APPpat
*)pat
)->_2
) {
277 #line 136 "indexing.pcc"
278 indexing(priority
, ((Pat_APPpat
*)pat
)->_2
, POSint(((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->tag
+ ((TyCon_DATATYPEtycon
*)((Ty_TYCONty
*)((Pat_CONSpat
*)((Pat_APPpat
*)pat
)->_1
)->CONSpat
->alg_ty
)->_1
)->unit
, pos
), index_map
); return;
279 #line 136 "indexing.pcc"
282 default: { goto L6
; } break;
286 default: { goto L6
; } break;
291 default: { goto L6
; } break;
295 case a_Pat::tag_TYPEDpat
: {
296 #line 130 "indexing.pcc"
297 pat
= ((Pat_TYPEDpat
*)pat
)->_1
;
298 #line 130 "indexing.pcc"
300 case a_Pat::tag_ASpat
: {
301 #line 129 "indexing.pcc"
302 pat
= ((Pat_ASpat
*)pat
)->_2
;
303 #line 129 "indexing.pcc"
305 case a_Pat::tag_CONTEXTpat
: {
306 #line 132 "indexing.pcc"
307 pat
= ((Pat_CONTEXTpat
*)pat
)->_2
;
308 #line 132 "indexing.pcc"
310 case a_Pat::tag_ARRAYpat
: {
311 #line 138 "indexing.pcc"
312 indexing(priority
, ((Pat_ARRAYpat
*)pat
)->_1
, pos
, index_map
); return;
313 #line 138 "indexing.pcc"
315 case a_Pat::tag_TUPLEpat
: {
316 #line 137 "indexing.pcc"
317 indexing(priority
, ((Pat_TUPLEpat
*)pat
)->TUPLEpat
, pos
, index_map
); return;
318 #line 137 "indexing.pcc"
320 case a_Pat::tag_RECORDpat
: {
321 #line 142 "indexing.pcc"
322 for_each(LabPat
, p
, ((Pat_RECORDpat
*)pat
)->_1
)
323 indexing(priority
, p
.pat
, POSlabel(p
.label
,pos
), index_map
);
326 #line 145 "indexing.pcc"
328 case a_Pat::tag_VECTORpat
: {
329 #line 140 "indexing.pcc"
331 #line 140 "indexing.pcc"
332 #line 140 "indexing.pcc"
333 list_1_(((Pat_VECTORpat
*)pat
)->len
,((Pat_VECTORpat
*)pat
)->elements
)
334 #line 140 "indexing.pcc"
335 #line 140 "indexing.pcc"
336 , pos
, index_map
); return;
337 #line 140 "indexing.pcc"
339 case a_Pat::tag_LOGICALpat
: {
340 #line 146 "indexing.pcc"
341 indexing(priority
,((Pat_LOGICALpat
*)pat
)->_2
,pos
,index_map
); pat
= ((Pat_LOGICALpat
*)pat
)->_3
;
342 #line 146 "indexing.pcc"
344 case a_Pat::tag_MARKEDpat
: {
345 #line 131 "indexing.pcc"
346 pat
= ((Pat_MARKEDpat
*)pat
)->_2
;
347 #line 131 "indexing.pcc"
349 default: { goto L6
; } break;
355 #line 147 "indexing.pcc"
356 #line 147 "indexing.pcc"
360 ///////////////////////////////////////////////////////////////////////////////
362 // Method to compute the indices.
364 ///////////////////////////////////////////////////////////////////////////////
365 void indexing(int priority
, Pats pats
, Pos pos
, HashTable
& index_map
)
370 // initialize the pattern array
371 { for_each (Pat
, p
, pats
) Ps
[i
++] = p
; }
373 if (n
<= 0 || n
> 32) return;
375 // compute the set of index positions for this pattern list
376 unsigned long indices
= 0;
377 for (i
= 0; i
< n
; i
++)
378 if (is_refutable(Ps
[i
])) indices
|= 1 << i
;
380 // Locate the position ranking
381 HashTable::Entry
* e
= index_map
.lookup(pos
);
384 // Heuristic to update the ranks given new index and priority
386 ranks
= (int*)index_map
.value(e
);
389 // Initialize the new ranking array.
390 // Put all used positions in front and
391 // the rest the the back.
392 ranks
= (int*)mem_pool
[n
* sizeof(int)];
394 for (i
= 0; i
< n
; i
++) if (indices
& (1 << i
)) ranks
[j
++] = i
;
395 for (i
= 0; i
< n
; i
++) if (! (indices
& (1 << i
))) ranks
[j
++] = i
;
396 index_map
.insert(pos
, ranks
);
399 // Recursive on subcomponents, and insert an adaptive rank.
400 for (i
= 0; i
< n
; i
++)
401 indexing(priority
, Ps
[i
], POSadaptive(i
,ranks
,pos
), index_map
);
404 ///////////////////////////////////////////////////////////////////////////////
406 // Method to compute the indices information for a set of pattern matching
409 ///////////////////////////////////////////////////////////////////////////////
410 void indexing (MatchRules rules
, HashTable
& index_map
)
412 for_each (MatchRule
, r
, rules
)
414 #line 203 "indexing.pcc"
415 #line 207 "indexing.pcc"
417 #line 205 "indexing.pcc"
418 indexing(priority
, r
->_2
, POSzero
, index_map
);
421 #line 207 "indexing.pcc"
423 #line 208 "indexing.pcc"
424 #line 208 "indexing.pcc"
428 #line 211 "indexing.pcc"
430 ------------------------------- Statistics -------------------------------
431 Merge matching rules = yes
432 Number of DFA nodes merged = 201
433 Number of ifs generated = 14
434 Number of switches generated = 8
437 Adaptive matching = enabled
438 Fast string matching = disabled
439 Inline downcasts = enabled
440 --------------------------------------------------------------------------