Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 45... Line 75...
45
 * 	    x B,
75
 * 	    x B,
46
 * 	    y A,
76
 * 	    y A,
47
 * 	    z A,
77
 * 	    z A,
48
 * 	    y B;
78
 * 	    y B;
49
 *
79
 *
50
 * would be reordered to:
80
 * would be reordered to:
51
 *
81
 *
52
 * 	A = x A,
82
 * 	A = x A,
53
 * 	    x B,
83
 * 	    x B,
54
 * 	    y A,
84
 * 	    y A,
55
 * 	    y B,
85
 * 	    y B,
56
 * 	    z A;
86
 * 	    z A;
Line 58... Line 88...
58
 * and three groups would have been created:
88
 * and three groups would have been created:
59
 *
89
 *
60
 * 	x A, x B
90
 * 	x A, x B
61
 *
91
 *
62
 * 	y A, y B
92
 * 	y A, y B
63
 *
93
 *
64
 * 	z A
94
 * 	z A
65
 *
95
 *
66
 * Each group has its first set calculated (this is the union of the first
96
 * Each group has its first set calculated (this is the union of the first
67
 * sets of each of the alternatives in the group), and its priority.  The
97
 * sets of each of the alternatives in the group), and its priority.  The
68
 * priority of a group is one more than the priority of the rule with the
98
 * priority of a group is one more than the priority of the rule with the
Line 100... Line 130...
100
 * expanded in all alternatives in the group, putting the new alternatives at
130
 * expanded in all alternatives in the group, putting the new alternatives at
101
 * the end of the rule.  It then recalculates the groups for the new
131
 * the end of the rule.  It then recalculates the groups for the new
102
 * alternatives, and tries again.
132
 * alternatives, and tries again.
103
 *
133
 *
104
 * 4. The last stage is to change a group of the form:
134
 * 4. The last stage is to change a group of the form:
105
 *
135
 *
106
 * 	  B C
136
 * 	  B C
107
 * 	| B D
137
 * 	| B D
108
 *
138
 *
109
 * into
139
 * into
110
 *
140
 *
111
 * 	  B X
141
 * 	  B X
112
 *
142
 *
113
 * 	X = C
143
 * 	X = C
114
 * 	  | D
144
 * 	  | D
115
 *
145
 *
116
 * where "X" is a newly created rule.  The algorithm actually removes all
146
 * where "X" is a newly created rule.  The algorithm actually removes all
117
 * initial items that are the same for all members of the group.  It also
147
 * initial items that are the same for all members of the group.  It also
118
 * performs renaming of the result names of the final item in the group of
148
 * performs renaming of the result names of the final item in the group of
119
 * identical items if necessary.
149
 * identical items if necessary.
120
 * 
150
 *
121
 * It is possible that this final stage of the factorization process will go
151
 * It is possible that this final stage of the factorization process will go
122
 * on forever.  To prevent this, there is a limit on the number of new rules
152
 * on forever.  To prevent this, there is a limit on the number of new rules
123
 * that can be created.  This stage of the factorisation process is
153
 * that can be created.  This stage of the factorisation process is
124
 * implemented by the functions ``rule_factor_2'', ``rule_factor_3'', and
154
 * implemented by the functions ``rule_factor_2'', ``rule_factor_3'', and
125
 * ``rule_factor_4''.
155
 * ``rule_factor_4''.
Line 171... Line 201...
171
 
201
 
172
static unsigned			rule_factor_limit = 1000;
202
static unsigned			rule_factor_limit = 1000;
173
 
203
 
174
/*--------------------------------------------------------------------------*/
204
/*--------------------------------------------------------------------------*/
175
 
205
 
176
static unsigned			rule_overlaps
-
 
177
	PROTO_S ((ItemP, BitVecP, EntryListP));
206
static unsigned			rule_overlaps(ItemP, BitVecP, EntryListP);
178
 
207
 
179
static AltGroupP
208
static AltGroupP
180
group_create PROTO_N ((item, alt_ref))
209
group_create(ItemP item, AltP *alt_ref)
181
	     PROTO_T (ItemP item X
-
 
182
		      AltP *alt_ref)
-
 
183
{
210
{
184
    AltGroupP group = ALLOCATE (AltGroupT);
211
    AltGroupP group = ALLOCATE(AltGroupT);
185
 
212
 
186
    group->next     = NIL (AltGroupP);
213
    group->next     = NIL(AltGroupP);
187
    bitvec_init (&(group->first_set));
214
    bitvec_init(&(group->first_set));
188
    entry_list_init (&(group->predicate_first));
215
    entry_list_init(&(group->predicate_first));
189
    group->priority = rule_overlaps (item, &(group->first_set),
216
    group->priority = rule_overlaps(item, &(group->first_set),
190
				     &(group->predicate_first));
217
				    &(group->predicate_first));
191
    group->alt_ref  = alt_ref;
218
    group->alt_ref  = alt_ref;
192
    return (group);
219
    return(group);
193
}
220
}
194
 
221
 
195
static AltGroupP
222
static AltGroupP
196
group_deallocate PROTO_N ((group))
223
group_deallocate(AltGroupP group)
197
		 PROTO_T (AltGroupP group)
-
 
198
{
224
{
199
    AltGroupP next = group->next;
225
    AltGroupP next = group->next;
200
 
226
 
201
    bitvec_destroy (&(group->first_set));
227
    bitvec_destroy(&(group->first_set));
202
    entry_list_destroy (&(group->predicate_first));
228
    entry_list_destroy(&(group->predicate_first));
203
    DEALLOCATE (group);
229
    DEALLOCATE(group);
204
    return (next);
230
    return(next);
205
}
231
}
206
 
232
 
207
/*--------------------------------------------------------------------------*/
233
/*--------------------------------------------------------------------------*/
208
 
234
 
209
static unsigned
235
static unsigned
210
rule_overlaps PROTO_N ((initial_item, first_set, predicate_first))
236
rule_overlaps(ItemP initial_item, BitVecP first_set, EntryListP predicate_first)
211
	      PROTO_T (ItemP      initial_item X
-
 
212
		       BitVecP    first_set X
-
 
213
		       EntryListP predicate_first)
-
 
214
{
237
{
215
    unsigned priority    = 0;
238
    unsigned priority    = 0;
216
    BoolT    see_through = TRUE;
239
    BoolT    see_through = TRUE;
217
    BoolT    no_action   = TRUE;
240
    BoolT    no_action   = TRUE;
218
    ItemP    item;
241
    ItemP    item;
219
 
242
 
220
    for (item = initial_item; see_through && (item != NIL (ItemP));
243
    for (item = initial_item; see_through && (item != NIL(ItemP));
221
	 item = item_next (item)) {
244
	 item = item_next(item)) {
222
	switch (item_type (item)) EXHAUSTIVE {
245
	switch (item_type(item))EXHAUSTIVE {
223
	  case ET_PREDICATE:
246
	  case ET_PREDICATE:
224
	    ASSERT (item == initial_item);
247
	    ASSERT(item == initial_item);
225
	    entry_list_add_if_missing (predicate_first, item_entry (item));
248
	    entry_list_add_if_missing(predicate_first, item_entry(item));
226
	    see_through = FALSE;
249
	    see_through = FALSE;
227
	    break;
250
	    break;
228
	  case ET_RENAME:
251
	  case ET_RENAME:
229
	  case ET_ACTION:
252
	  case ET_ACTION:
230
	    no_action = FALSE;
253
	    no_action = FALSE;
231
	    break;
254
	    break;
232
	  case ET_RULE: {
255
	  case ET_RULE: {
233
	      EntryP   entry         = item_entry (item);
256
	      EntryP   entry         = item_entry(item);
234
	      RuleP    item_rule     = entry_get_rule (entry);
257
	      RuleP    item_rule     = entry_get_rule(entry);
235
	      unsigned item_priority = rule_get_priority (item_rule);
258
	      unsigned item_priority = rule_get_priority(item_rule);
236
 
259
 
237
	      bitvec_or (first_set, rule_first_set (item_rule));
260
	      bitvec_or(first_set, rule_first_set(item_rule));
238
	      entry_list_append (predicate_first,
261
	      entry_list_append(predicate_first,
239
				 rule_predicate_first (item_rule));
262
				rule_predicate_first(item_rule));
240
	      see_through = rule_is_see_through (item_rule);
263
	      see_through = rule_is_see_through(item_rule);
241
	      if ((item_priority > priority) && no_action) {
264
	      if ((item_priority > priority) && no_action) {
242
		  priority = item_priority;
265
		  priority = item_priority;
243
	      }
266
	      }
244
	  }
267
	  }
245
	    break;
268
	    break;
246
	  case ET_BASIC: {
269
	  case ET_BASIC: {
247
	      BasicP basic = entry_get_basic (item_entry (item));
270
	      BasicP basic = entry_get_basic(item_entry(item));
248
 
271
 
249
	      see_through = FALSE;
272
	      see_through = FALSE;
250
	      bitvec_set (first_set, basic_terminal (basic));
273
	      bitvec_set(first_set, basic_terminal(basic));
251
	  }
274
	  }
252
	    break;
275
	    break;
253
	  case ET_NON_LOCAL:
276
	  case ET_NON_LOCAL:
254
	  case ET_NAME:
277
	  case ET_NAME:
255
	  case ET_TYPE:
278
	  case ET_TYPE:
256
	    UNREACHED;
279
	    UNREACHED;
257
	}
280
	}
258
    }
281
    }
259
    return (priority + 1);
282
    return(priority + 1);
260
}
283
}
261
 
284
 
262
static void
285
static void
263
rule_group_by_initial_item PROTO_N ((rule, groups))
286
rule_group_by_initial_item(RuleP rule, AltGroupListP groups)
264
			   PROTO_T (RuleP         rule X
-
 
265
				    AltGroupListP groups)
-
 
266
{
287
{
267
    AltP *alt_ref = (rule->alt_tail);
288
    AltP *alt_ref = (rule->alt_tail);
268
    AltP  alt;
289
    AltP  alt;
269
 
290
 
270
  next_alt:
291
  next_alt:
271
    while ((alt = *alt_ref) != NIL (AltP)) {
292
    while ((alt = *alt_ref) != NIL(AltP)) {
272
	ItemP     item = alt_item_head (alt);
293
	ItemP     item = alt_item_head(alt);
273
	AltGroupP group;
294
	AltGroupP group;
274
 
295
 
275
	for (group = groups->head; group; group = group->next) {
296
	for (group = groups->head; group; group = group->next) {
276
	    AltP *group_alt_ref = group->alt_ref;
297
	    AltP *group_alt_ref = group->alt_ref;
277
	    ItemP alt_item      = alt_item_head (*group_alt_ref);
298
	    ItemP alt_item      = alt_item_head(*group_alt_ref);
278
 
299
 
279
	    if (((item_entry (item) == item_entry (alt_item)) &&
300
	    if (((item_entry(item) == item_entry(alt_item)) &&
280
		 types_equal_numbers (item_param (item),
301
		 types_equal_numbers(item_param(item), item_param(alt_item)) &&
281
				      item_param (alt_item)) &&
-
 
282
		 types_equal_numbers (item_result (item),
302
		 types_equal_numbers(item_result(item),
283
				      item_result (alt_item))) ||
303
				     item_result(alt_item))) ||
284
		(item_is_rename (item) && item_is_rename (alt_item) &&
304
		(item_is_rename(item) && item_is_rename(alt_item) &&
285
		 types_equal_names (item_param (item),
305
		 types_equal_names(item_param(item), item_param(alt_item)) &&
286
				    item_param (alt_item)) &&
-
 
287
		 types_equal_names (item_result (item),
306
		 types_equal_names(item_result(item),
288
				    item_result (alt_item)))) {
307
				   item_result(alt_item)))) {
289
		unsigned priority;
308
		unsigned priority;
290
 
309
 
291
		*alt_ref        = alt_next (alt);
310
		*alt_ref        = alt_next(alt);
292
		alt_set_next (alt, *group_alt_ref);
311
		alt_set_next(alt, *group_alt_ref);
293
		*group_alt_ref  = alt;
312
		*group_alt_ref  = alt;
294
		priority        = rule_overlaps (item, &(group->first_set),
313
		priority        = rule_overlaps(item, &(group->first_set),
295
						 &(group->predicate_first));
314
						&(group->predicate_first));
296
		if (priority > group->priority) {
315
		if (priority > group->priority) {
297
		    group->priority = priority;
316
		    group->priority = priority;
298
		}
317
		}
299
		goto next_alt;
318
		goto next_alt;
300
	    }
319
	    }
301
	}
320
	}
302
	group           = group_create (item, alt_ref);
321
	group           = group_create(item, alt_ref);
303
	*(groups->tail) = group;
322
	*(groups->tail) = group;
304
	groups->tail    = &(group->next);
323
	groups->tail    = &(group->next);
305
	alt_ref         = alt_next_ref (alt);
324
	alt_ref         = alt_next_ref(alt);
306
    }
325
    }
307
    rule->alt_tail = alt_ref;
326
    rule->alt_tail = alt_ref;
308
}
327
}
309
 
328
 
310
static void			rule_factor_1
-
 
311
	PROTO_S ((RuleP, FactorClosureP));
329
static void			rule_factor_1(RuleP, FactorClosureP);
312
 
330
 
313
static void
331
static void
314
rule_expand PROTO_N ((rule, closure, group, groups))
332
rule_expand(RuleP rule, FactorClosureP closure, AltGroupP group,
315
	    PROTO_T (RuleP          rule X
-
 
316
		     FactorClosureP closure X
-
 
317
		     AltGroupP      group X
-
 
318
		     AltGroupListP  groups)
333
	    AltGroupListP groups)
319
{
334
{
320
    AltP       alt       = (*(group->alt_ref));
335
    AltP       alt       = (*(group->alt_ref));
321
    ItemP      item      = alt_item_head (alt);
336
    ItemP      item      = alt_item_head(alt);
322
    RuleP      item_rule = entry_get_rule (item_entry (item));
337
    RuleP      item_rule = entry_get_rule(item_entry(item));
323
    AltP       handler   = rule_get_handler (item_rule);
338
    AltP       handler   = rule_get_handler(item_rule);
324
    AltGroupP *last;
339
    AltGroupP *last;
325
    AltP      *tail;
340
    AltP      *tail;
326
    TypeTransT translator;
341
    TypeTransT translator;
327
 
342
 
328
    rule_factor_1 (item_rule, closure);
343
    rule_factor_1(item_rule, closure);
329
    if (handler && (!alt_equal (handler, rule_get_handler (rule)))) {
344
    if (handler && (!alt_equal(handler, rule_get_handler(rule)))) {
330
	E_factor_handler_mismatch (item_rule, rule);
345
	E_factor_handler_mismatch(item_rule, rule);
331
    }
346
    }
332
    if (!non_local_list_is_empty (rule_non_locals (item_rule))) {
347
    if (!non_local_list_is_empty(rule_non_locals(item_rule))) {
333
	E_factor_nl_entry (item_rule, rule);
348
	E_factor_nl_entry(item_rule, rule);
334
    }
349
    }
335
    for (last = &(groups->head); *last != group; last = &((*last)->next)) {
350
    for (last = &(groups->head); *last != group; last = &((*last)->next)) {
336
	/*NOTHING*/
351
	/*NOTHING*/
337
    }
352
    }
338
    if (((*last) = (group->next)) != NIL (AltGroupP)) {
353
    if (((*last) = (group->next)) != NIL(AltGroupP)) {
339
	*(group->alt_ref)       = *(group->next->alt_ref);
354
	*(group->alt_ref)      = *(group->next->alt_ref);
340
	*(group->next->alt_ref) = NIL (AltP);
355
	*(group->next->alt_ref) = NIL(AltP);
341
	group->next->alt_ref    = group->alt_ref;
356
	group->next->alt_ref    = group->alt_ref;
342
    } else {
357
    } else {
343
	groups->tail            = last;
358
	groups->tail            = last;
344
	*(group->alt_ref)       = NIL (AltP);
359
	*(group->alt_ref)      = NIL(AltP);
345
	rule->alt_tail          = group->alt_ref;
360
	rule->alt_tail          = group->alt_ref;
346
    }
361
    }
347
    (void) group_deallocate (group);
362
   (void)group_deallocate(group);
348
    tail = rule->alt_tail;
363
    tail = rule->alt_tail;
349
    while (alt) {
364
    while (alt) {
350
	AltP       item_alt = rule_alt_head (item_rule);
365
	AltP       item_alt = rule_alt_head(item_rule);
351
	SaveTransT state;
366
	SaveTransT state;
352
 
367
 
353
	trans_init (&translator, rule_param (rule), rule_result (rule), alt);
368
	trans_init(&translator, rule_param(rule), rule_result(rule), alt);
354
	trans_add_translations (&translator, rule_param (item_rule),
369
	trans_add_translations(&translator, rule_param(item_rule),
355
				item_param (alt_item_head (alt)));
370
			       item_param(alt_item_head(alt)));
356
	trans_add_translations (&translator, rule_result (item_rule),
371
	trans_add_translations(&translator, rule_result(item_rule),
357
				item_result (alt_item_head (alt)));
372
			       item_result(alt_item_head(alt)));
358
	trans_save_state (&translator, &state);
373
	trans_save_state(&translator, &state);
359
	if (rule_has_empty_alt (item_rule)) {
374
	if (rule_has_empty_alt(item_rule)) {
360
	    AltP new_alt = alt_create_merge (NIL (ItemP),
375
	    AltP new_alt = alt_create_merge(NIL(ItemP),
361
					     item_next (alt_item_head (alt)),
376
					    item_next(alt_item_head(alt)),
362
					     &translator, closure->table);
377
					    &translator, closure->table);
363
 
378
 
364
	    *tail = new_alt;
379
	    *tail = new_alt;
365
	    tail  = alt_next_ref (new_alt);
380
	    tail  = alt_next_ref(new_alt);
366
	    trans_restore_state (&translator, &state);
381
	    trans_restore_state(&translator, &state);
367
	}
382
	}
368
	for (; item_alt; item_alt = alt_next (item_alt)) {
383
	for (; item_alt; item_alt = alt_next(item_alt)) {
369
	    AltP new_alt = alt_create_merge (alt_item_head (item_alt),
384
	    AltP new_alt = alt_create_merge(alt_item_head(item_alt),
370
					     item_next (alt_item_head (alt)),
385
					    item_next(alt_item_head(alt)),
371
					     &translator, closure->table);
386
					    &translator, closure->table);
372
 
387
 
373
	    *tail = new_alt;
388
	    *tail = new_alt;
374
	    tail  = alt_next_ref (new_alt);
389
	    tail  = alt_next_ref(new_alt);
375
	    trans_restore_state (&translator, &state);
390
	    trans_restore_state(&translator, &state);
376
	}
391
	}
377
	trans_destroy (&translator);
392
	trans_destroy(&translator);
378
	alt = alt_deallocate (alt);
393
	alt = alt_deallocate(alt);
379
    }
394
    }
380
}
395
}
381
 
396
 
382
static BoolT
397
static BoolT
383
rule_expand_item_clashes PROTO_N ((rule, closure, groups))
398
rule_expand_item_clashes(RuleP rule, FactorClosureP closure,
384
			 PROTO_T (RuleP          rule X
-
 
385
				  FactorClosureP closure X
-
 
386
				  AltGroupListP  groups)
399
			 AltGroupListP groups)
387
{
400
{
388
    BitVecP   bitvec1 = &(closure->bitvec1);
401
    BitVecP   bitvec1 = &(closure->bitvec1);
389
    BitVecP   bitvec2 = &(closure->bitvec2);
402
    BitVecP   bitvec2 = &(closure->bitvec2);
390
    AltGroupP group;
403
    AltGroupP group;
391
 
404
 
392
    for (group = groups->head; group; group = group->next) {
405
    for (group = groups->head; group; group = group->next) {
393
	AltGroupP group2;
406
	AltGroupP group2;
394
	AltP      first_alt = (*(group->alt_ref));
407
	AltP      first_alt = (*(group->alt_ref));
395
	ItemP     item      = alt_item_head (first_alt);
408
	ItemP     item      = alt_item_head(first_alt);
396
 
409
 
397
	if (item_is_rule (item)) {
410
	if (item_is_rule(item)) {
398
	    RuleP item_rule = entry_get_rule (item_entry (item));
411
	    RuleP item_rule = entry_get_rule(item_entry(item));
399
 
412
 
400
	    if (!entry_list_is_empty (rule_predicate_first (item_rule))) {
413
	    if (!entry_list_is_empty(rule_predicate_first(item_rule))) {
401
		rule_expand (rule, closure, group, groups);
414
		rule_expand(rule, closure, group, groups);
402
		return (TRUE);
415
		return(TRUE);
403
	    } else if (rule_is_see_through (item_rule)) {
416
	    } else if (rule_is_see_through(item_rule)) {
404
		AltP       alt = first_alt;
417
		AltP       alt = first_alt;
405
		AltP       end = NIL (AltP);
418
		AltP       end = NIL(AltP);
406
		EntryListT predicate_first;
419
		EntryListT predicate_first;
407
 
420
 
408
		if (group->next) {
421
		if (group->next) {
409
		    end = *(group->next->alt_ref);
422
		    end = *(group->next->alt_ref);
410
		}
423
		}
411
		bitvec_replace (bitvec1, rule_first_set (item_rule));
424
		bitvec_replace(bitvec1, rule_first_set(item_rule));
412
		do {
425
		do {
413
		    bitvec_empty (bitvec2);
426
		    bitvec_empty(bitvec2);
414
		    entry_list_init (&predicate_first);
427
		    entry_list_init(&predicate_first);
415
		    (void) rule_overlaps (item_next (alt_item_head (alt)),
428
		   (void)rule_overlaps(item_next(alt_item_head(alt)),
416
					  bitvec2, &predicate_first);
429
				       bitvec2, &predicate_first);
417
		    if (bitvec_intersects (bitvec1, bitvec2) ||
430
		    if (bitvec_intersects(bitvec1, bitvec2) ||
418
			(!entry_list_is_empty (&predicate_first))) {
431
			(!entry_list_is_empty(&predicate_first))) {
419
			entry_list_destroy (&predicate_first);
432
			entry_list_destroy(&predicate_first);
420
			rule_expand (rule, closure, group, groups);
433
			rule_expand(rule, closure, group, groups);
421
			return (TRUE);
434
			return(TRUE);
422
		    }
435
		    }
423
		    entry_list_destroy (&predicate_first);
436
		    entry_list_destroy(&predicate_first);
424
		} while ((alt = alt_next (alt)) != end);
437
		} while ((alt = alt_next(alt)) != end);
425
	    }
438
	    }
426
	    for (group2 = groups->head; group2; group2 = group2->next) {
439
	    for (group2 = groups->head; group2; group2 = group2->next) {
427
		if ((group2 != group) &&
440
		if ((group2 != group) &&
428
		    (bitvec_intersects (&(group2->first_set),
441
		   (bitvec_intersects(&(group2->first_set),
429
					&(group->first_set)))) {
442
				      &(group->first_set)))) {
430
		    if (group->priority > group2->priority) {
443
		    if (group->priority > group2->priority) {
431
			rule_expand (rule, closure, group, groups);
444
			rule_expand(rule, closure, group, groups);
432
		    } else {
445
		    } else {
433
			rule_expand (rule, closure, group2, groups);
446
			rule_expand(rule, closure, group2, groups);
434
		    }
447
		    }
435
		    return (TRUE);
448
		    return(TRUE);
436
		}
449
		}
437
	    }
450
	    }
438
	}
451
	}
439
    }
452
    }
440
    return (FALSE);
453
    return(FALSE);
441
}
454
}
442
 
455
 
443
/*--------------------------------------------------------------------------*/
456
/*--------------------------------------------------------------------------*/
444
 
457
 
445
static ItemP
458
static ItemP
446
rule_create_factored PROTO_N ((params, result, alt, table))
459
rule_create_factored(TypeTupleP params, TypeTupleP result, AltP alt,
447
		     PROTO_T (TypeTupleP params X
-
 
448
			      TypeTupleP result X
-
 
449
			      AltP       alt X
-
 
450
			      TableP     table)
460
		     TableP table)
451
{
461
{
452
    static unsigned factorised_rules = 0;
462
    static unsigned factorised_rules = 0;
453
    EntryP          new_entry;
463
    EntryP          new_entry;
454
    ItemP           new_item;
464
    ItemP           new_item;
455
    RuleP           new_rule;
465
    RuleP           new_rule;
456
 
466
 
457
    if (factorised_rules == rule_factor_limit) {
467
    if (factorised_rules == rule_factor_limit) {
458
	E_too_many_factorisations (rule_factor_limit);
468
	E_too_many_factorisations(rule_factor_limit);
459
	UNREACHED;
469
	UNREACHED;
460
    }
470
    }
461
    factorised_rules ++;
471
    factorised_rules ++;
462
    new_entry = table_add_generated_rule (table, FALSE);
472
    new_entry = table_add_generated_rule(table, FALSE);
463
    new_rule  = entry_get_rule (new_entry);
473
    new_rule  = entry_get_rule(new_entry);
464
    types_copy (rule_param (new_rule), params);
474
    types_copy(rule_param(new_rule), params);
465
    types_copy (rule_result (new_rule), result);
475
    types_copy(rule_result(new_rule), result);
466
    while (alt) {
476
    while (alt) {
467
	AltP tmp_alt = alt;
477
	AltP tmp_alt = alt;
468
 
478
 
469
	alt = alt_next (alt);
479
	alt = alt_next(alt);
470
	alt_set_next (tmp_alt, NIL (AltP));
480
	alt_set_next(tmp_alt, NIL(AltP));
471
	if (alt_item_head (tmp_alt)) {
481
	if (alt_item_head(tmp_alt)) {
472
	    rule_add_alt (new_rule, tmp_alt);
482
	    rule_add_alt(new_rule, tmp_alt);
473
	} else {
483
	} else {
474
	    rule_add_empty_alt (new_rule);
484
	    rule_add_empty_alt(new_rule);
475
	    (void) alt_deallocate (tmp_alt);
485
	   (void)alt_deallocate(tmp_alt);
476
	}
486
	}
477
    }
487
    }
478
    rule_compute_first_set_1 (new_rule);
488
    rule_compute_first_set_1(new_rule);
479
    new_item  = item_create (new_entry);
489
    new_item  = item_create(new_entry);
480
    types_assign (item_param (new_item), params);
490
    types_assign(item_param(new_item), params);
481
    types_assign (item_result (new_item), result);
491
    types_assign(item_result(new_item), result);
482
    types_make_references (rule_param (new_rule), item_param (new_item));
492
    types_make_references(rule_param(new_rule), item_param(new_item));
483
    return (new_item);
493
    return(new_item);
484
}
494
}
485
 
495
 
486
static BoolT
496
static BoolT
487
rule_factor_4 PROTO_N ((rule, old_alt, new_alt, table, predicate_id, params,
497
rule_factor_4(RuleP rule, AltP old_alt, AltP new_alt, TableP table,
488
		     items_equal_ref))
-
 
489
	      PROTO_T (RuleP      rule X
-
 
490
		       AltP       old_alt X
-
 
491
		       AltP       new_alt X
-
 
492
		       TableP     table X
-
 
493
		       EntryP     predicate_id X
-
 
494
		       TypeTupleP params X
-
 
495
		       BoolP      items_equal_ref)
498
	      EntryP predicate_id, TypeTupleP params, BoolP items_equal_ref)
496
{
499
{
497
    ItemP       old_item     = alt_item_head (old_alt);
500
    ItemP       old_item     = alt_item_head(old_alt);
498
    BoolT       result_equal = TRUE;
501
    BoolT       result_equal = TRUE;
499
    AltP        alt;
502
    AltP        alt;
500
    TypeBTransT translator;
503
    TypeBTransT translator;
501
 
504
 
502
    for (alt = alt_next (old_alt); alt; alt = alt_next (alt)) {
505
    for (alt = alt_next(old_alt); alt; alt = alt_next(alt)) {
503
	ItemP item = alt_item_head (alt);
506
	ItemP item = alt_item_head(alt);
504
 
507
 
505
	if (((item == NIL (ItemP)) && (old_item != NIL (ItemP))) ||
508
	if (((item == NIL(ItemP)) && (old_item != NIL(ItemP))) ||
506
	    ((item != NIL (ItemP)) && (old_item == NIL (ItemP)))) {
509
	    ((item != NIL(ItemP)) && (old_item == NIL(ItemP)))) {
507
	    *items_equal_ref = FALSE;
510
	    *items_equal_ref = FALSE;
508
	    return (TRUE);
511
	    return(TRUE);
509
	} else if ((item == NIL (ItemP)) && (old_item == NIL (ItemP))) {
512
	} else if ((item == NIL(ItemP)) && (old_item == NIL(ItemP))) {
510
	    /*NOTHING*/
513
	    /*NOTHING*/
511
	} else if (((item_entry (old_item) == item_entry (item)) &&
514
	} else if (((item_entry(old_item) == item_entry(item)) &&
512
		    types_equal_numbers (item_param (old_item),
515
		    types_equal_numbers(item_param(old_item),
513
					 item_param (item)) &&
516
					item_param(item)) &&
514
		    types_equal_numbers (item_result (old_item),
517
		    types_equal_numbers(item_result(old_item),
515
					 item_result (item))) ||
518
					item_result(item))) ||
516
		   (item_is_rename (item) && item_is_rename (old_item) &&
519
		   (item_is_rename(item) && item_is_rename(old_item) &&
517
		    types_equal_names (item_param (item),
520
		    types_equal_names(item_param(item),
518
				       item_param (old_item)) &&
521
				      item_param(old_item)) &&
519
		    types_equal_names (item_result (item),
522
		    types_equal_names(item_result(item),
520
				       item_result (old_item)))) {
523
				      item_result(old_item)))) {
521
	    if (result_equal) {
524
	    if (result_equal) {
522
		result_equal = types_equal_names (item_result (old_item),
525
		result_equal = types_equal_names(item_result(old_item),
523
						  item_result (item));
526
						 item_result(item));
524
	    }
527
	    }
525
	} else {
528
	} else {
526
	    *items_equal_ref = FALSE;
529
	    *items_equal_ref = FALSE;
527
	    return (TRUE);
530
	    return(TRUE);
528
	}
531
	}
529
    }
532
    }
530
    if (old_item == NIL (ItemP)) {
533
    if (old_item == NIL(ItemP)) {
531
	*items_equal_ref = FALSE;
534
	*items_equal_ref = FALSE;
532
	return (FALSE);
535
	return(FALSE);
533
    }
536
    }
534
    btrans_init (&translator);
537
    btrans_init(&translator);
535
    for (alt = old_alt; alt; alt = alt_next (alt)) {
538
    for (alt = old_alt; alt; alt = alt_next(alt)) {
536
	ItemP item = alt_unlink_item_head (alt);
539
	ItemP item = alt_unlink_item_head(alt);
537
 
540
 
538
	if (!result_equal) {
541
	if (!result_equal) {
539
	    ItemP new_item;
542
	    ItemP new_item;
540
 
543
 
541
	    if (alt == old_alt) {
544
	    if (alt == old_alt) {
542
		new_item = btrans_generate_non_pred_names (&translator,
545
		new_item = btrans_generate_non_pred_names(&translator,
543
							   item_result (item),
546
							  item_result(item),
544
							   rule_result (rule),
547
							  rule_result(rule),
545
							   predicate_id,
548
							  predicate_id, table);
546
							   table);
-
 
547
		types_translate (item_result (item), &translator);
549
		types_translate(item_result(item), &translator);
548
	    } else {
550
	    } else {
549
		new_item = btrans_regen_non_pred_names (&translator,
551
		new_item = btrans_regen_non_pred_names(&translator,
550
							item_result (item),
552
						       item_result(item),
551
							rule_result (rule),
553
						       rule_result(rule),
552
							table);
554
						       table);
553
	    }
555
	    }
554
	    item_translate_list (alt_item_head (alt), &translator);
556
	    item_translate_list(alt_item_head(alt), &translator);
555
	    if (new_item) {
557
	    if (new_item) {
556
		alt_add_item (alt, new_item);
558
		alt_add_item(alt, new_item);
557
	    }
559
	    }
558
	}
560
	}
559
	if (alt == old_alt) {
561
	if (alt == old_alt) {
560
	    types_add_new_names (params, item_result (item), predicate_id);
562
	    types_add_new_names(params, item_result(item), predicate_id);
561
	    alt_add_item (new_alt, item);
563
	    alt_add_item(new_alt, item);
562
	} else {
564
	} else {
563
	    (void) item_deallocate (item);
565
	   (void)item_deallocate(item);
564
	}
566
	}
565
    }
567
    }
566
    btrans_destroy (&translator);
568
    btrans_destroy(&translator);
567
    return (TRUE);
569
    return(TRUE);
568
}
570
}
569
 
571
 
570
static void
572
static void
571
rule_factor_3 PROTO_N ((rule, table, predicate_id, old_alt, new_alt))
573
rule_factor_3(RuleP rule, TableP table, EntryP predicate_id, AltP old_alt,
572
	      PROTO_T (RuleP  rule X
-
 
573
		       TableP table X
-
 
574
		       EntryP predicate_id X
-
 
575
		       AltP   old_alt X
-
 
576
		       AltP   new_alt)
574
	      AltP new_alt)
577
{
575
{
578
    BoolT       items_equal = TRUE;
576
    BoolT       items_equal = TRUE;
579
    BoolT       found_items;
577
    BoolT       found_items;
580
    TypeTupleT  params;
578
    TypeTupleT  params;
581
    TypeTupleT  result;
579
    TypeTupleT  result;
582
 
580
 
583
    types_copy (&params, rule_param (rule));
581
    types_copy(&params, rule_param(rule));
584
    types_copy (&result, rule_result (rule));
582
    types_copy(&result, rule_result(rule));
585
    do {
583
    do {
586
	found_items = rule_factor_4 (rule, old_alt, new_alt, table,
584
	found_items = rule_factor_4(rule, old_alt, new_alt, table,
587
				     predicate_id, &params, &items_equal);
585
				    predicate_id, &params, &items_equal);
588
    } while (items_equal);
586
    } while (items_equal);
589
    if (found_items) {
587
    if (found_items) {
590
	ItemP new_item;
588
	ItemP new_item;
591
 
589
 
592
	types_unlink_used (&result, &params);
590
	types_unlink_used(&result, &params);
593
	types_unlink_unused (&params, old_alt);
591
	types_unlink_unused(&params, old_alt);
594
	new_item = rule_create_factored (&params, &result, old_alt, table);
592
	new_item = rule_create_factored(&params, &result, old_alt, table);
595
	alt_add_item (new_alt, new_item);
593
	alt_add_item(new_alt, new_item);
596
    } else {
594
    } else {
597
	types_destroy (&params);
595
	types_destroy(&params);
598
	while (old_alt) {
596
	while (old_alt) {
599
	    AltP tmp_alt = old_alt;
597
	    AltP tmp_alt = old_alt;
600
 
598
 
601
	    old_alt = alt_next (old_alt);
599
	    old_alt = alt_next(old_alt);
602
	    ASSERT (alt_item_head (tmp_alt) == NIL (ItemP));
600
	    ASSERT(alt_item_head(tmp_alt) == NIL(ItemP));
603
	    (void) alt_deallocate (tmp_alt);
601
	   (void)alt_deallocate(tmp_alt);
604
	}
602
	}
605
    }
603
    }
606
}
604
}
607
 
605
 
608
static void
606
static void
609
rule_factor_2 PROTO_N ((rule, table, predicate_id, groups))
607
rule_factor_2(RuleP rule, TableP table, EntryP predicate_id,
610
	      PROTO_T (RuleP         rule X
-
 
611
		       TableP        table X
-
 
612
		       EntryP        predicate_id X
-
 
613
		       AltGroupListP groups)
608
	      AltGroupListP groups)
614
{
609
{
615
    AltGroupP group;
610
    AltGroupP group;
616
 
611
 
617
    for (group = groups->head; group; group = group_deallocate (group)) {
612
    for (group = groups->head; group; group = group_deallocate(group)) {
618
	AltP alt = *(group->alt_ref);
613
	AltP alt = *(group->alt_ref);
619
	AltP new_alt;
614
	AltP new_alt;
620
 
615
 
621
	if (group->next) {
616
	if (group->next) {
622
	    if (group->next->alt_ref == alt_next_ref (*(group->alt_ref))) {
617
	    if (group->next->alt_ref == alt_next_ref(*(group->alt_ref))) {
623
		goto done;
618
		goto done;
624
	    }
619
	    }
625
	    new_alt                 = alt_create ();
620
	    new_alt                 = alt_create();
626
	    alt_set_next (new_alt, *(group->next->alt_ref));
621
	    alt_set_next(new_alt, *(group->next->alt_ref));
627
	    *(group->next->alt_ref) = NIL (AltP);
622
	    *(group->next->alt_ref) = NIL(AltP);
628
	    group->next->alt_ref    = alt_next_ref (new_alt);
623
	    group->next->alt_ref    = alt_next_ref(new_alt);
629
	} else {
624
	} else {
630
	    if (alt_next (*(group->alt_ref)) == NIL (AltP)) {
625
	    if (alt_next(*(group->alt_ref)) == NIL(AltP)) {
631
		goto done;
626
		goto done;
632
	    }
627
	    }
633
	    new_alt        = alt_create ();
628
	    new_alt        = alt_create();
634
	    rule->alt_tail = alt_next_ref (new_alt);
629
	    rule->alt_tail = alt_next_ref(new_alt);
635
	}
630
	}
636
	*(group->alt_ref) = new_alt;
631
	*(group->alt_ref) = new_alt;
637
	rule_factor_3 (rule, table, predicate_id, alt, new_alt);
632
	rule_factor_3(rule, table, predicate_id, alt, new_alt);
638
      done:;
633
      done:;
639
    }
634
    }
640
}
635
}
641
 
636
 
642
static void
637
static void
643
rule_factor_1 PROTO_N ((rule, closure))
638
rule_factor_1(RuleP rule, FactorClosureP closure)
644
	      PROTO_T (RuleP          rule X
-
 
645
		       FactorClosureP closure)
-
 
646
{
639
{
647
    AltGroupListT groups;
640
    AltGroupListT groups;
648
 
641
 
649
    groups.head = NIL (AltGroupP);
642
    groups.head = NIL(AltGroupP);
650
    groups.tail = &(groups.head);
643
    groups.tail = &(groups.head);
651
    if (rule_is_factored (rule)) {
644
    if (rule_is_factored(rule)) {
652
	return;
645
	return;
653
    }
646
    }
654
    rule_factored (rule);
647
    rule_factored(rule);
655
    rule->alt_tail = &(rule->alt_head);
648
    rule->alt_tail = &(rule->alt_head);
656
    do {
649
    do {
657
	rule_renumber (rule, FALSE, closure->predicate_id);
650
	rule_renumber(rule, FALSE, closure->predicate_id);
658
	rule_group_by_initial_item (rule, &groups);
651
	rule_group_by_initial_item(rule, &groups);
659
    } while (rule_expand_item_clashes (rule, closure, &groups));
652
    } while (rule_expand_item_clashes(rule, closure, &groups));
660
    rule_factor_2 (rule, closure->table, closure->predicate_id, &groups);
653
    rule_factor_2(rule, closure->table, closure->predicate_id, &groups);
661
}
654
}
662
 
655
 
663
/*--------------------------------------------------------------------------*/
656
/*--------------------------------------------------------------------------*/
664
 
657
 
665
void
658
void
666
rule_factor PROTO_N ((entry, gclosure))
659
rule_factor(EntryP entry, GenericP gclosure)
667
	    PROTO_T (EntryP   entry X
-
 
668
		     GenericP gclosure)
-
 
669
{
660
{
670
    FactorClosureP closure = (FactorClosureP) gclosure;
661
    FactorClosureP closure = (FactorClosureP)gclosure;
671
 
662
 
672
    if (entry_is_rule (entry)) {
663
    if (entry_is_rule(entry)) {
673
	RuleP rule = entry_get_rule (entry);
664
	RuleP rule = entry_get_rule(entry);
674
 
665
 
675
	rule_factor_1 (rule, closure);
666
	rule_factor_1(rule, closure);
676
    }
667
    }
677
}
668
}
678
 
669
 
679
void
670
void
680
rule_set_factor_limit PROTO_N ((limit))
671
rule_set_factor_limit(unsigned limit)
681
		      PROTO_T (unsigned limit)
-
 
682
{
672
{
683
    rule_factor_limit = limit;
673
    rule_factor_limit = limit;
684
}
674
}
685

675

686
/*
676
/*