Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 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
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/*** rule-factor.c --- Factorisation of rules.
62
 *
63
 ** Author: Steve Folkes <smf@hermes.mod.uk>
64
 *
65
 *** Commentary:
66
 *
67
 * This file implements the SID factorisation routines.
68
 *
69
 * The factorisation process consists of the following phases:
70
 *
71
 * 1. The rule is reordered so that alternatives with the same initial item
72
 * are grouped together, for example the rule:
73
 *
74
 * 	A = x A,
75
 * 	    x B,
76
 * 	    y A,
77
 * 	    z A,
78
 * 	    y B;
79
 *
80
 * would be reordered to:
81
 *
82
 * 	A = x A,
83
 * 	    x B,
84
 * 	    y A,
85
 * 	    y B,
86
 * 	    z A;
87
 *
88
 * and three groups would have been created:
89
 *
90
 * 	x A, x B
91
 *
92
 * 	y A, y B
93
 *
94
 * 	z A
95
 *
96
 * Each group has its first set calculated (this is the union of the first
97
 * sets of each of the alternatives in the group), and its priority.  The
98
 * priority of a group is one more than the priority of the rule with the
99
 * highest priority in any of the group's alternatives, which is not preceded
100
 * by an action.  If there is no such rule, then the group's priority is one.
101
 *
102
 * The ``rule_group_by_initial_item'' function is responsible for this
103
 * re-ordering.  It uses the rule's alternative tail pointer (``alt_tail'') to
104
 * indicate where in the rule it should start the grouping from.  Nothing
105
 * before this point is modified (it is assumed that it is already grouped).
106
 * The pointer will always be restored to the end of the alternative list by
107
 * the time this function returns.
108
 *
109
 * 2. Having split the rule up into groups, it then looks at each group to see
110
 * if there are alternatives of the form:
111
 *
112
 * 	B C ...
113
 *
114
 * where "B" is a see through rule, and the first set of "B" contains some
115
 * terminals from the first set of "C ...".  If it finds any, it removes the
116
 * group from the rule, and expands "B" in all alternatives in the group,
117
 * putting the new alternatives at the end of the rule.  It also looks for
118
 * alternatives that begin with a rule which has a predicate in its first set,
119
 * in which case it also expands the rule in all alternatives in the group.
120
 * It then recomputes the groups for the new alternatives, and tries again.
121
 * This phase and the next phase are implemented by the function
122
 * ``rule_expand_item_clashes''.  It is not possible to expand a rule that has
123
 * an exception handler into another rule that has an exception handler
124
 * (unless the exception handlers are identical).
125
 *
126
 * 3. The next phase is to check to see if any of the groups have common
127
 * terminals in their first sets.  If this is the case (and the first item in
128
 * each alternative in at least one of the groups is a rule), then the group
129
 * with the highest priority is removed from the rule, and the first item is
130
 * expanded in all alternatives in the group, putting the new alternatives at
131
 * the end of the rule.  It then recalculates the groups for the new
132
 * alternatives, and tries again.
133
 *
134
 * 4. The last stage is to change a group of the form:
135
 *
136
 * 	  B C
137
 * 	| B D
138
 *
139
 * into
140
 *
141
 * 	  B X
142
 *
143
 * 	X = C
144
 * 	  | D
145
 *
146
 * where "X" is a newly created rule.  The algorithm actually removes all
147
 * initial items that are the same for all members of the group.  It also
148
 * performs renaming of the result names of the final item in the group of
149
 * identical items if necessary.
6 7u83 150
 *
2 7u83 151
 * It is possible that this final stage of the factorization process will go
152
 * on forever.  To prevent this, there is a limit on the number of new rules
153
 * that can be created.  This stage of the factorisation process is
154
 * implemented by the functions ``rule_factor_2'', ``rule_factor_3'', and
155
 * ``rule_factor_4''.
156
 *
157
 * When the new rule is created, the ``rule_compute_first_set_1'' function is
158
 * called to calculate its first set, whether or not it is see through and its
159
 * priority.  The new rules are created untraced, to ensure that the
160
 * factorisation process will be applied to them as well.
161
 *
162
 *** Change Log:
163
 * $Log: rule-factor.c,v $
164
 * Revision 1.1.1.1  1998/01/17  15:57:46  release
165
 * First version to be checked into rolling release.
166
 *
167
 * Revision 1.2  1994/12/15  09:58:37  smf
168
 * Brought into line with OSSG C Coding Standards Document, as per
169
 * "CR94_178.sid+tld-update".
170
 *
171
 * Revision 1.1.1.1  1994/07/25  16:04:38  smf
172
 * Initial import of SID 1.8 non shared files.
173
 *
174
**/
175
 
176
/****************************************************************************/
177
 
178
#include "rule.h"
179
#include "basic.h"
180
#include "bitvec.h"
181
#include "entry-list.h"
182
#include "gen-errors.h"
183
#include "types.h"
184
 
185
/*--------------------------------------------------------------------------*/
186
 
187
typedef struct AltGroupT {
188
    struct AltGroupT	       *next;
189
    BitVecT			first_set;
190
    EntryListT			predicate_first;
191
    unsigned			priority;
192
    AltP		       *alt_ref;
193
} AltGroupT, *AltGroupP;
194
 
195
typedef struct AltGroupListT {
196
    AltGroupP			head;
197
    AltGroupP		       *tail;
198
} AltGroupListT, *AltGroupListP;
199
 
200
/*--------------------------------------------------------------------------*/
201
 
202
static unsigned			rule_factor_limit = 1000;
203
 
204
/*--------------------------------------------------------------------------*/
205
 
6 7u83 206
static unsigned			rule_overlaps(ItemP, BitVecP, EntryListP);
2 7u83 207
 
208
static AltGroupP
6 7u83 209
group_create(ItemP item, AltP *alt_ref)
2 7u83 210
{
6 7u83 211
    AltGroupP group = ALLOCATE(AltGroupT);
2 7u83 212
 
6 7u83 213
    group->next     = NIL(AltGroupP);
214
    bitvec_init(&(group->first_set));
215
    entry_list_init(&(group->predicate_first));
216
    group->priority = rule_overlaps(item, &(group->first_set),
217
				    &(group->predicate_first));
2 7u83 218
    group->alt_ref  = alt_ref;
6 7u83 219
    return(group);
2 7u83 220
}
221
 
222
static AltGroupP
6 7u83 223
group_deallocate(AltGroupP group)
2 7u83 224
{
225
    AltGroupP next = group->next;
226
 
6 7u83 227
    bitvec_destroy(&(group->first_set));
228
    entry_list_destroy(&(group->predicate_first));
229
    DEALLOCATE(group);
230
    return(next);
2 7u83 231
}
232
 
233
/*--------------------------------------------------------------------------*/
234
 
235
static unsigned
6 7u83 236
rule_overlaps(ItemP initial_item, BitVecP first_set, EntryListP predicate_first)
2 7u83 237
{
238
    unsigned priority    = 0;
239
    BoolT    see_through = TRUE;
240
    BoolT    no_action   = TRUE;
241
    ItemP    item;
242
 
6 7u83 243
    for (item = initial_item; see_through && (item != NIL(ItemP));
244
	 item = item_next(item)) {
245
	switch (item_type(item))EXHAUSTIVE {
2 7u83 246
	  case ET_PREDICATE:
6 7u83 247
	    ASSERT(item == initial_item);
248
	    entry_list_add_if_missing(predicate_first, item_entry(item));
2 7u83 249
	    see_through = FALSE;
250
	    break;
251
	  case ET_RENAME:
252
	  case ET_ACTION:
253
	    no_action = FALSE;
254
	    break;
255
	  case ET_RULE: {
6 7u83 256
	      EntryP   entry         = item_entry(item);
257
	      RuleP    item_rule     = entry_get_rule(entry);
258
	      unsigned item_priority = rule_get_priority(item_rule);
2 7u83 259
 
6 7u83 260
	      bitvec_or(first_set, rule_first_set(item_rule));
261
	      entry_list_append(predicate_first,
262
				rule_predicate_first(item_rule));
263
	      see_through = rule_is_see_through(item_rule);
2 7u83 264
	      if ((item_priority > priority) && no_action) {
265
		  priority = item_priority;
266
	      }
267
	  }
268
	    break;
269
	  case ET_BASIC: {
6 7u83 270
	      BasicP basic = entry_get_basic(item_entry(item));
2 7u83 271
 
272
	      see_through = FALSE;
6 7u83 273
	      bitvec_set(first_set, basic_terminal(basic));
2 7u83 274
	  }
275
	    break;
276
	  case ET_NON_LOCAL:
277
	  case ET_NAME:
278
	  case ET_TYPE:
279
	    UNREACHED;
280
	}
281
    }
6 7u83 282
    return(priority + 1);
2 7u83 283
}
284
 
285
static void
6 7u83 286
rule_group_by_initial_item(RuleP rule, AltGroupListP groups)
2 7u83 287
{
288
    AltP *alt_ref = (rule->alt_tail);
289
    AltP  alt;
290
 
291
  next_alt:
6 7u83 292
    while ((alt = *alt_ref) != NIL(AltP)) {
293
	ItemP     item = alt_item_head(alt);
2 7u83 294
	AltGroupP group;
295
 
296
	for (group = groups->head; group; group = group->next) {
297
	    AltP *group_alt_ref = group->alt_ref;
6 7u83 298
	    ItemP alt_item      = alt_item_head(*group_alt_ref);
2 7u83 299
 
6 7u83 300
	    if (((item_entry(item) == item_entry(alt_item)) &&
301
		 types_equal_numbers(item_param(item), item_param(alt_item)) &&
302
		 types_equal_numbers(item_result(item),
303
				     item_result(alt_item))) ||
304
		(item_is_rename(item) && item_is_rename(alt_item) &&
305
		 types_equal_names(item_param(item), item_param(alt_item)) &&
306
		 types_equal_names(item_result(item),
307
				   item_result(alt_item)))) {
2 7u83 308
		unsigned priority;
309
 
6 7u83 310
		*alt_ref        = alt_next(alt);
311
		alt_set_next(alt, *group_alt_ref);
2 7u83 312
		*group_alt_ref  = alt;
6 7u83 313
		priority        = rule_overlaps(item, &(group->first_set),
314
						&(group->predicate_first));
2 7u83 315
		if (priority > group->priority) {
316
		    group->priority = priority;
317
		}
318
		goto next_alt;
319
	    }
320
	}
6 7u83 321
	group           = group_create(item, alt_ref);
2 7u83 322
	*(groups->tail) = group;
323
	groups->tail    = &(group->next);
6 7u83 324
	alt_ref         = alt_next_ref(alt);
2 7u83 325
    }
326
    rule->alt_tail = alt_ref;
327
}
328
 
6 7u83 329
static void			rule_factor_1(RuleP, FactorClosureP);
2 7u83 330
 
331
static void
6 7u83 332
rule_expand(RuleP rule, FactorClosureP closure, AltGroupP group,
333
	    AltGroupListP groups)
2 7u83 334
{
335
    AltP       alt       = (*(group->alt_ref));
6 7u83 336
    ItemP      item      = alt_item_head(alt);
337
    RuleP      item_rule = entry_get_rule(item_entry(item));
338
    AltP       handler   = rule_get_handler(item_rule);
2 7u83 339
    AltGroupP *last;
340
    AltP      *tail;
341
    TypeTransT translator;
342
 
6 7u83 343
    rule_factor_1(item_rule, closure);
344
    if (handler && (!alt_equal(handler, rule_get_handler(rule)))) {
345
	E_factor_handler_mismatch(item_rule, rule);
2 7u83 346
    }
6 7u83 347
    if (!non_local_list_is_empty(rule_non_locals(item_rule))) {
348
	E_factor_nl_entry(item_rule, rule);
2 7u83 349
    }
350
    for (last = &(groups->head); *last != group; last = &((*last)->next)) {
351
	/*NOTHING*/
352
    }
6 7u83 353
    if (((*last) = (group->next)) != NIL(AltGroupP)) {
354
	*(group->alt_ref)      = *(group->next->alt_ref);
355
	*(group->next->alt_ref) = NIL(AltP);
2 7u83 356
	group->next->alt_ref    = group->alt_ref;
357
    } else {
358
	groups->tail            = last;
6 7u83 359
	*(group->alt_ref)      = NIL(AltP);
2 7u83 360
	rule->alt_tail          = group->alt_ref;
361
    }
6 7u83 362
   (void)group_deallocate(group);
2 7u83 363
    tail = rule->alt_tail;
364
    while (alt) {
6 7u83 365
	AltP       item_alt = rule_alt_head(item_rule);
2 7u83 366
	SaveTransT state;
367
 
6 7u83 368
	trans_init(&translator, rule_param(rule), rule_result(rule), alt);
369
	trans_add_translations(&translator, rule_param(item_rule),
370
			       item_param(alt_item_head(alt)));
371
	trans_add_translations(&translator, rule_result(item_rule),
372
			       item_result(alt_item_head(alt)));
373
	trans_save_state(&translator, &state);
374
	if (rule_has_empty_alt(item_rule)) {
375
	    AltP new_alt = alt_create_merge(NIL(ItemP),
376
					    item_next(alt_item_head(alt)),
377
					    &translator, closure->table);
2 7u83 378
 
379
	    *tail = new_alt;
6 7u83 380
	    tail  = alt_next_ref(new_alt);
381
	    trans_restore_state(&translator, &state);
2 7u83 382
	}
6 7u83 383
	for (; item_alt; item_alt = alt_next(item_alt)) {
384
	    AltP new_alt = alt_create_merge(alt_item_head(item_alt),
385
					    item_next(alt_item_head(alt)),
386
					    &translator, closure->table);
2 7u83 387
 
388
	    *tail = new_alt;
6 7u83 389
	    tail  = alt_next_ref(new_alt);
390
	    trans_restore_state(&translator, &state);
2 7u83 391
	}
6 7u83 392
	trans_destroy(&translator);
393
	alt = alt_deallocate(alt);
2 7u83 394
    }
395
}
396
 
397
static BoolT
6 7u83 398
rule_expand_item_clashes(RuleP rule, FactorClosureP closure,
399
			 AltGroupListP groups)
2 7u83 400
{
401
    BitVecP   bitvec1 = &(closure->bitvec1);
402
    BitVecP   bitvec2 = &(closure->bitvec2);
403
    AltGroupP group;
404
 
405
    for (group = groups->head; group; group = group->next) {
406
	AltGroupP group2;
407
	AltP      first_alt = (*(group->alt_ref));
6 7u83 408
	ItemP     item      = alt_item_head(first_alt);
2 7u83 409
 
6 7u83 410
	if (item_is_rule(item)) {
411
	    RuleP item_rule = entry_get_rule(item_entry(item));
2 7u83 412
 
6 7u83 413
	    if (!entry_list_is_empty(rule_predicate_first(item_rule))) {
414
		rule_expand(rule, closure, group, groups);
415
		return(TRUE);
416
	    } else if (rule_is_see_through(item_rule)) {
2 7u83 417
		AltP       alt = first_alt;
6 7u83 418
		AltP       end = NIL(AltP);
2 7u83 419
		EntryListT predicate_first;
420
 
421
		if (group->next) {
422
		    end = *(group->next->alt_ref);
423
		}
6 7u83 424
		bitvec_replace(bitvec1, rule_first_set(item_rule));
2 7u83 425
		do {
6 7u83 426
		    bitvec_empty(bitvec2);
427
		    entry_list_init(&predicate_first);
428
		   (void)rule_overlaps(item_next(alt_item_head(alt)),
429
				       bitvec2, &predicate_first);
430
		    if (bitvec_intersects(bitvec1, bitvec2) ||
431
			(!entry_list_is_empty(&predicate_first))) {
432
			entry_list_destroy(&predicate_first);
433
			rule_expand(rule, closure, group, groups);
434
			return(TRUE);
2 7u83 435
		    }
6 7u83 436
		    entry_list_destroy(&predicate_first);
437
		} while ((alt = alt_next(alt)) != end);
2 7u83 438
	    }
439
	    for (group2 = groups->head; group2; group2 = group2->next) {
440
		if ((group2 != group) &&
6 7u83 441
		   (bitvec_intersects(&(group2->first_set),
442
				      &(group->first_set)))) {
2 7u83 443
		    if (group->priority > group2->priority) {
6 7u83 444
			rule_expand(rule, closure, group, groups);
2 7u83 445
		    } else {
6 7u83 446
			rule_expand(rule, closure, group2, groups);
2 7u83 447
		    }
6 7u83 448
		    return(TRUE);
2 7u83 449
		}
450
	    }
451
	}
452
    }
6 7u83 453
    return(FALSE);
2 7u83 454
}
455
 
456
/*--------------------------------------------------------------------------*/
457
 
458
static ItemP
6 7u83 459
rule_create_factored(TypeTupleP params, TypeTupleP result, AltP alt,
460
		     TableP table)
2 7u83 461
{
462
    static unsigned factorised_rules = 0;
463
    EntryP          new_entry;
464
    ItemP           new_item;
465
    RuleP           new_rule;
466
 
467
    if (factorised_rules == rule_factor_limit) {
6 7u83 468
	E_too_many_factorisations(rule_factor_limit);
2 7u83 469
	UNREACHED;
470
    }
471
    factorised_rules ++;
6 7u83 472
    new_entry = table_add_generated_rule(table, FALSE);
473
    new_rule  = entry_get_rule(new_entry);
474
    types_copy(rule_param(new_rule), params);
475
    types_copy(rule_result(new_rule), result);
2 7u83 476
    while (alt) {
477
	AltP tmp_alt = alt;
478
 
6 7u83 479
	alt = alt_next(alt);
480
	alt_set_next(tmp_alt, NIL(AltP));
481
	if (alt_item_head(tmp_alt)) {
482
	    rule_add_alt(new_rule, tmp_alt);
2 7u83 483
	} else {
6 7u83 484
	    rule_add_empty_alt(new_rule);
485
	   (void)alt_deallocate(tmp_alt);
2 7u83 486
	}
487
    }
6 7u83 488
    rule_compute_first_set_1(new_rule);
489
    new_item  = item_create(new_entry);
490
    types_assign(item_param(new_item), params);
491
    types_assign(item_result(new_item), result);
492
    types_make_references(rule_param(new_rule), item_param(new_item));
493
    return(new_item);
2 7u83 494
}
495
 
496
static BoolT
6 7u83 497
rule_factor_4(RuleP rule, AltP old_alt, AltP new_alt, TableP table,
498
	      EntryP predicate_id, TypeTupleP params, BoolP items_equal_ref)
2 7u83 499
{
6 7u83 500
    ItemP       old_item     = alt_item_head(old_alt);
2 7u83 501
    BoolT       result_equal = TRUE;
502
    AltP        alt;
503
    TypeBTransT translator;
504
 
6 7u83 505
    for (alt = alt_next(old_alt); alt; alt = alt_next(alt)) {
506
	ItemP item = alt_item_head(alt);
2 7u83 507
 
6 7u83 508
	if (((item == NIL(ItemP)) && (old_item != NIL(ItemP))) ||
509
	    ((item != NIL(ItemP)) && (old_item == NIL(ItemP)))) {
2 7u83 510
	    *items_equal_ref = FALSE;
6 7u83 511
	    return(TRUE);
512
	} else if ((item == NIL(ItemP)) && (old_item == NIL(ItemP))) {
2 7u83 513
	    /*NOTHING*/
6 7u83 514
	} else if (((item_entry(old_item) == item_entry(item)) &&
515
		    types_equal_numbers(item_param(old_item),
516
					item_param(item)) &&
517
		    types_equal_numbers(item_result(old_item),
518
					item_result(item))) ||
519
		   (item_is_rename(item) && item_is_rename(old_item) &&
520
		    types_equal_names(item_param(item),
521
				      item_param(old_item)) &&
522
		    types_equal_names(item_result(item),
523
				      item_result(old_item)))) {
2 7u83 524
	    if (result_equal) {
6 7u83 525
		result_equal = types_equal_names(item_result(old_item),
526
						 item_result(item));
2 7u83 527
	    }
528
	} else {
529
	    *items_equal_ref = FALSE;
6 7u83 530
	    return(TRUE);
2 7u83 531
	}
532
    }
6 7u83 533
    if (old_item == NIL(ItemP)) {
2 7u83 534
	*items_equal_ref = FALSE;
6 7u83 535
	return(FALSE);
2 7u83 536
    }
6 7u83 537
    btrans_init(&translator);
538
    for (alt = old_alt; alt; alt = alt_next(alt)) {
539
	ItemP item = alt_unlink_item_head(alt);
2 7u83 540
 
541
	if (!result_equal) {
542
	    ItemP new_item;
543
 
544
	    if (alt == old_alt) {
6 7u83 545
		new_item = btrans_generate_non_pred_names(&translator,
546
							  item_result(item),
547
							  rule_result(rule),
548
							  predicate_id, table);
549
		types_translate(item_result(item), &translator);
2 7u83 550
	    } else {
6 7u83 551
		new_item = btrans_regen_non_pred_names(&translator,
552
						       item_result(item),
553
						       rule_result(rule),
554
						       table);
2 7u83 555
	    }
6 7u83 556
	    item_translate_list(alt_item_head(alt), &translator);
2 7u83 557
	    if (new_item) {
6 7u83 558
		alt_add_item(alt, new_item);
2 7u83 559
	    }
560
	}
561
	if (alt == old_alt) {
6 7u83 562
	    types_add_new_names(params, item_result(item), predicate_id);
563
	    alt_add_item(new_alt, item);
2 7u83 564
	} else {
6 7u83 565
	   (void)item_deallocate(item);
2 7u83 566
	}
567
    }
6 7u83 568
    btrans_destroy(&translator);
569
    return(TRUE);
2 7u83 570
}
571
 
572
static void
6 7u83 573
rule_factor_3(RuleP rule, TableP table, EntryP predicate_id, AltP old_alt,
574
	      AltP new_alt)
2 7u83 575
{
576
    BoolT       items_equal = TRUE;
577
    BoolT       found_items;
578
    TypeTupleT  params;
579
    TypeTupleT  result;
580
 
6 7u83 581
    types_copy(&params, rule_param(rule));
582
    types_copy(&result, rule_result(rule));
2 7u83 583
    do {
6 7u83 584
	found_items = rule_factor_4(rule, old_alt, new_alt, table,
585
				    predicate_id, &params, &items_equal);
2 7u83 586
    } while (items_equal);
587
    if (found_items) {
588
	ItemP new_item;
589
 
6 7u83 590
	types_unlink_used(&result, &params);
591
	types_unlink_unused(&params, old_alt);
592
	new_item = rule_create_factored(&params, &result, old_alt, table);
593
	alt_add_item(new_alt, new_item);
2 7u83 594
    } else {
6 7u83 595
	types_destroy(&params);
2 7u83 596
	while (old_alt) {
597
	    AltP tmp_alt = old_alt;
598
 
6 7u83 599
	    old_alt = alt_next(old_alt);
600
	    ASSERT(alt_item_head(tmp_alt) == NIL(ItemP));
601
	   (void)alt_deallocate(tmp_alt);
2 7u83 602
	}
603
    }
604
}
605
 
606
static void
6 7u83 607
rule_factor_2(RuleP rule, TableP table, EntryP predicate_id,
608
	      AltGroupListP groups)
2 7u83 609
{
610
    AltGroupP group;
611
 
6 7u83 612
    for (group = groups->head; group; group = group_deallocate(group)) {
2 7u83 613
	AltP alt = *(group->alt_ref);
614
	AltP new_alt;
615
 
616
	if (group->next) {
6 7u83 617
	    if (group->next->alt_ref == alt_next_ref(*(group->alt_ref))) {
2 7u83 618
		goto done;
619
	    }
6 7u83 620
	    new_alt                 = alt_create();
621
	    alt_set_next(new_alt, *(group->next->alt_ref));
622
	    *(group->next->alt_ref) = NIL(AltP);
623
	    group->next->alt_ref    = alt_next_ref(new_alt);
2 7u83 624
	} else {
6 7u83 625
	    if (alt_next(*(group->alt_ref)) == NIL(AltP)) {
2 7u83 626
		goto done;
627
	    }
6 7u83 628
	    new_alt        = alt_create();
629
	    rule->alt_tail = alt_next_ref(new_alt);
2 7u83 630
	}
631
	*(group->alt_ref) = new_alt;
6 7u83 632
	rule_factor_3(rule, table, predicate_id, alt, new_alt);
2 7u83 633
      done:;
634
    }
635
}
636
 
637
static void
6 7u83 638
rule_factor_1(RuleP rule, FactorClosureP closure)
2 7u83 639
{
640
    AltGroupListT groups;
641
 
6 7u83 642
    groups.head = NIL(AltGroupP);
2 7u83 643
    groups.tail = &(groups.head);
6 7u83 644
    if (rule_is_factored(rule)) {
2 7u83 645
	return;
646
    }
6 7u83 647
    rule_factored(rule);
2 7u83 648
    rule->alt_tail = &(rule->alt_head);
649
    do {
6 7u83 650
	rule_renumber(rule, FALSE, closure->predicate_id);
651
	rule_group_by_initial_item(rule, &groups);
652
    } while (rule_expand_item_clashes(rule, closure, &groups));
653
    rule_factor_2(rule, closure->table, closure->predicate_id, &groups);
2 7u83 654
}
655
 
656
/*--------------------------------------------------------------------------*/
657
 
658
void
6 7u83 659
rule_factor(EntryP entry, GenericP gclosure)
2 7u83 660
{
6 7u83 661
    FactorClosureP closure = (FactorClosureP)gclosure;
2 7u83 662
 
6 7u83 663
    if (entry_is_rule(entry)) {
664
	RuleP rule = entry_get_rule(entry);
2 7u83 665
 
6 7u83 666
	rule_factor_1(rule, closure);
2 7u83 667
    }
668
}
669
 
670
void
6 7u83 671
rule_set_factor_limit(unsigned limit)
2 7u83 672
{
673
    rule_factor_limit = limit;
674
}
675
 
676
/*
677
 * Local variables(smf):
678
 * eval: (include::add-path-entry "../os-interface" "../library")
679
 * eval: (include::add-path-entry "../generated")
680
 * end:
681
**/