Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/*** rule-lre.c --- Left recursion elimination routines.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID left recursion elimination routines.
38
 *
39
 * The generic cycle detection functions defined in the file ``rule.c'' are
40
 * used to find left cycles in the grammar (this is done by the function
41
 * ``grammar_remove_left_recursion'' in the file "grammar.c").  If the
42
 * functions find any such cycles, the function ``rule_remove_left_cycle'' is
43
 * called on the group of productions to remove the left recursion.  Left
44
 * recursion is transformed into right recursion in the manner described
45
 * below.
46
 *
47
 * Given a set of productions, expressed as
48
 *
49
 *	Ai = Aj Bji, Ci;
50
 *
51
 * this can be transformed into
52
 *
53
 *	Ai  = Cj Xji;
54
 *	Xij = Yij, Bik Xkj;
55
 *
56
 * Where the rules "Xij" are generated automatically, and Yij is the identity
57
 * operation if i = j, or an error otherwise.  The generated rule has the same
58
 * parameters and results, which are the results of "Ai" augmented with those
59
 * parameters of "Ai" that are used by "Bji".
60
 *
61
 * In order for the transform to work, all of the "Ai" must have the same
62
 * parameter and result types, and the same exception handler.  Also, the
63
 * initial call to "Aj" must take exactly the formals of "Ai" as parameters.
64
 * This is checked by the ``rule_check_cycle_types'' function, which also
65
 * ensures that names are consistent throughout all of the rules.  The
66
 * transform is performed by the function ``rule_left_cycle_general_case''.
67
 *
68
 * In addition to the general case, two special cases are looked for.  The
69
 * first of these transforms:
70
 *
71
 *	A = A B, $;
72
 *
73
 * into
74
 *
75
 *	A = B A, $;
76
 *
77
 * whilst the second transforms:
78
 *
79
 *	A = A C B, B;
80
 *
81
 * into
82
 *
83
 *	A = B X;
84
 *	X = C A;
85
 *
86
 * These special cases are handled by the ``rule_left_cycle_special_case''
87
 * function.
88
 *
89
 *** Change Log:
90
 * $Log: rule-lre.c,v $
91
 * Revision 1.1.1.1  1998/01/17  15:57:47  release
92
 * First version to be checked into rolling release.
93
 *
94
 * Revision 1.3  1995/02/10  16:29:42  smf
95
 * Fixed bugs "CR95_111.sid-inline-no-var-check" and "CR95_112.sid-lre-var-call".
96
 *
97
 * Revision 1.2  1994/12/15  09:58:41  smf
98
 * Brought into line with OSSG C Coding Standards Document, as per
99
 * "CR94_178.sid+tld-update".
100
 *
101
 * Revision 1.1.1.1  1994/07/25  16:04:39  smf
102
 * Initial import of SID 1.8 non shared files.
103
 *
104
**/
105
 
106
/****************************************************************************/
107
 
108
#include "rule.h"
109
#include "dstring.h"
110
#include "gen-errors.h"
111
 
112
/*--------------------------------------------------------------------------*/
113
 
114
typedef struct MatrixEntryT {
115
    AltP			alt;
116
    BoolT			inited;
117
    TypeTupleT			param;
118
} MatrixEntryT, *MatrixEntryP;
119
 
120
typedef struct VectorEntryT {
121
    BoolT			empty_alt;
122
    AltP			alt;
123
    BoolT			inited;
124
    TypeTupleT			param;
125
} VectorEntryT, *VectorEntryP;
126
 
127
/*--------------------------------------------------------------------------*/
128
 
129
static MatrixEntryP
130
rule_left_cycle_matrix PROTO_N ((size))
131
		       PROTO_T (unsigned size)
132
{
133
    static MatrixEntryP array      = NIL (MatrixEntryP);
134
    static unsigned     array_size = 0;
135
    unsigned            i;
136
 
137
    if (size > array_size) {
138
	DEALLOCATE (array);
139
	array      = ALLOCATE_VECTOR (MatrixEntryT, size);
140
	array_size = size;
141
    }
142
    for (i = 0; i < size; i ++) {
143
	array [i].alt    = NIL (AltP);
144
	array [i].inited = FALSE;
145
    }
146
    return (array);
147
}
148
 
149
static VectorEntryP
150
rule_left_cycle_vector PROTO_N ((size))
151
		       PROTO_T (unsigned size)
152
{
153
    static VectorEntryP array      = NIL (VectorEntryP);
154
    static unsigned     array_size = 0;
155
    unsigned            i;
156
 
157
    if (size > array_size) {
158
	DEALLOCATE (array);
159
	array      = ALLOCATE_VECTOR (VectorEntryT, size);
160
	array_size = size;
161
    }
162
    for (i = 0; i < size; i ++) {
163
	array [i].empty_alt = FALSE;
164
	array [i].alt       = NIL (AltP);
165
	array [i].inited    = FALSE;
166
    }
167
    return (array);
168
}
169
 
170
static void
171
rule_destroy_cycle_matrix PROTO_N ((matrix, size))
172
			  PROTO_T (MatrixEntryP matrix X
173
				   unsigned     size)
174
{
175
    unsigned i;
176
 
177
    for (i = 0; i < size; i ++) {
178
	if (matrix [i].inited) {
179
	    AltP alt = matrix [i].alt;
180
 
181
	    while (alt) {
182
		alt = alt_deallocate (alt);
183
	    }
184
	    types_destroy (&(matrix [i].param));
185
	}
186
    }
187
}
188
 
189
static void
190
rule_destroy_cycle_vector PROTO_N ((vector, size))
191
			  PROTO_T (VectorEntryP vector X
192
				   unsigned     size)
193
{
194
    unsigned i;
195
 
196
    for (i = 0; i < size; i ++) {
197
	if (vector [i].inited) {
198
	    AltP alt = vector [i].alt;
199
 
200
	    while (alt) {
201
		alt = alt_deallocate (alt);
202
	    }
203
	    types_destroy (&(vector [i].param));
204
	}
205
    }
206
}
207
 
208
/*--------------------------------------------------------------------------*/
209
 
210
static ItemP
211
rule_find_suffix PROTO_N ((rec_item, non_rec_item))
212
		 PROTO_T (ItemP rec_item X
213
			  ItemP non_rec_item)
214
{
215
    ItemP    tmp_rec_item     = rec_item;
216
    ItemP    tmp_non_rec_item = non_rec_item;
217
    unsigned diff             = 0;
218
 
219
    while (tmp_rec_item && tmp_non_rec_item) {
220
	tmp_rec_item     = item_next (tmp_rec_item);
221
	tmp_non_rec_item = item_next (tmp_non_rec_item);
222
    }
223
    while (tmp_rec_item) {
224
	diff ++;
225
	tmp_rec_item = item_next (tmp_rec_item);
226
    }
227
    if (diff == 0) {
228
	return (NIL (ItemP));
229
    }
230
    do {
231
	rec_item = item_next (rec_item);
232
    } while (-- diff);
233
    tmp_rec_item     = rec_item;
234
    tmp_non_rec_item = non_rec_item;
235
    while (tmp_rec_item && tmp_non_rec_item) {
236
	if (item_entry (tmp_rec_item) != item_entry (tmp_non_rec_item)) {
237
	    return (NIL (ItemP));
238
	}
239
	tmp_rec_item     = item_next (tmp_rec_item);
240
	tmp_non_rec_item = item_next (tmp_non_rec_item);
241
    }
242
    ASSERT ((tmp_rec_item == NIL (ItemP)) &&
243
	    (tmp_non_rec_item == NIL (ItemP)));
244
    return (rec_item);
245
}
246
 
247
static void
248
rule_renumber_item_list PROTO_N ((item, translator))
249
			PROTO_T (ItemP       item X
250
				 TypeNTransP translator)
251
{
252
    ntrans_init (translator);
253
    for (; item; item = item_next (item)) {
254
	types_renumber (item_param (item), translator);
255
	types_renumber (item_result (item), translator);
256
    }
257
}
258
 
259
static BoolT
260
rule_compare_item_lists PROTO_N ((rec_suffix, non_rec_item))
261
			PROTO_T (ItemP rec_suffix X
262
				 ItemP non_rec_item)
263
{
264
    while (rec_suffix) {
265
	ASSERT (non_rec_item);
266
	if (!((types_equal_numbers (item_param (rec_suffix),
267
				    item_param (non_rec_item))) &&
268
	      (types_equal_numbers (item_result (rec_suffix),
269
				    item_result (non_rec_item))))) {
270
	    return (FALSE);
271
	}
272
	rec_suffix   = item_next (rec_suffix);
273
	non_rec_item = item_next (non_rec_item);
274
    }
275
    ASSERT (non_rec_item == NIL (ItemP));
276
    return (TRUE);
277
}
278
 
279
static void
280
rule_left_cycle_special_case_2 PROTO_N ((rule, table, non_rec_alt, rec_alt,
281
					 param, rec_suffix))
282
			       PROTO_T (RuleP      rule X
283
					TableP     table X
284
					AltP       non_rec_alt X
285
					AltP       rec_alt X
286
					TypeTupleP param X
287
					ItemP      rec_suffix)
288
{
289
    EntryP      entry    = table_add_generated_rule (table, TRUE);
290
    RuleP       new_rule = entry_get_rule (entry);
291
    ItemP       new_item = item_create (entry);
292
    ItemP       rec_item = alt_unlink_item_head (rec_alt);
293
    AltP        new_alt  = alt_create ();
294
    AltP        handler;
295
    ItemP       item;
296
    TypeBTransT tmp_trans;
297
    TypeTupleT  result;
298
 
299
    rule_reinit (rule);
300
    alt_set_next (non_rec_alt, NIL (AltP));
301
    btrans_init (&tmp_trans);
302
    types_copy (&result, rule_result (rule));
303
    btrans_generate_names (&tmp_trans, &result, table);
304
    types_translate (&result, &tmp_trans);
305
    if ((handler = rule_get_handler (rule)) != NIL (AltP)) {
306
	ItemP handler_items = alt_item_head (handler);
307
 
308
	item_translate_list (handler_items, &tmp_trans);
309
    }
310
    btrans_destroy (&tmp_trans);
311
    types_assign (item_param (new_item), rule_result (rule));
312
    types_copy (item_result (new_item), &result);
313
    types_copy (rule_result (rule), &result);
314
    alt_add_item (non_rec_alt, new_item);
315
    rule_add_alt (rule, non_rec_alt);
316
    types_copy (rule_param (new_rule), item_result (rec_item));
317
    types_copy (rule_result (new_rule), &result);
318
    (void) item_deallocate (rec_item);
319
    while (item = alt_item_head (rec_alt), item != rec_suffix) {
320
	alt_add_item (new_alt, alt_unlink_item_head (rec_alt));
321
    }
322
    (void) alt_deallocate (rec_alt);
323
    new_item = item_create (rule_entry (rule));
324
    if (param) {
325
	types_assign (item_param (new_item), param);
326
    } else {
327
	types_copy (item_param (new_item), rule_param (new_rule));
328
    }
329
    types_assign (item_result (new_item), &result);
330
    alt_add_item (new_alt, new_item);
331
    rule_add_alt (new_rule, new_alt);
332
    if (types_equal_zero_tuple (rule_param (new_rule))) {
333
	rule_add_empty_alt (new_rule);
334
    } else {
335
	new_alt  = alt_create ();
336
	new_item = item_create (table_add_rename (table));
337
	types_copy (item_param (new_item), rule_param (new_rule));
338
	types_copy (item_result (new_item), rule_result (new_rule));
339
	alt_add_item (new_alt, new_item);
340
	rule_add_alt (new_rule, new_alt);
341
    }
342
}
343
 
344
static BoolT
345
rule_left_cycle_special_case_1 PROTO_N ((rule, table))
346
			       PROTO_T (RuleP  rule X
347
					TableP table)
348
{
349
    AltP        rec_alt = rule_alt_head (rule);
350
    AltP        non_rec_alt;
351
    ItemP       rec_item;
352
    ItemP       rec_next;
353
    ItemP       rec_suffix;
354
    ItemP       non_rec_item;
355
    TypeTupleT  param;
356
    TypeNTransT rec_translator;
357
    TypeNTransT non_rec_translator;
358
 
359
    if (((non_rec_alt = alt_next (rec_alt)) == NIL (AltP)) ||
360
	(alt_next (non_rec_alt))) {
361
	return (FALSE);
362
    }
363
    if ((item_is_rule (non_rec_item = alt_item_head (non_rec_alt))) &&
364
	(entry_get_rule (item_entry (non_rec_item)) == rule)) {
365
	non_rec_alt  = rec_alt;
366
	rec_alt      = alt_next (rec_alt);
367
	non_rec_item = alt_item_head (non_rec_alt);
368
    }
369
    if ((item_is_rule (non_rec_item)) &&
370
	(entry_get_rule (item_entry (non_rec_item)) == rule)) {
371
	return (FALSE);
372
    }
373
    rec_item = alt_item_head (rec_alt);
374
    if (!((types_equal_names (rule_param (rule), item_param (rec_item))) &&
375
	  (types_equal (rule_param (rule), rule_result (rule))))) {
376
	return (FALSE);
377
    }
378
    rec_next = item_next (rec_item);
379
    if (item_names_used_in_list (rec_next, rule_param (rule))) {
380
	return (FALSE);
381
    }
382
    if ((rec_suffix = rule_find_suffix (rec_item, non_rec_item)) ==
383
	NIL (ItemP)) {
384
	return (FALSE);
385
    }
386
    if ((rec_suffix != rec_next) &&
387
	(item_names_used_in_list (rec_suffix, item_result (rec_item)))) {
388
	return (FALSE);
389
    }
390
    rule_renumber_item_list (non_rec_item, &non_rec_translator);
391
    rule_renumber_item_list (rec_suffix, &rec_translator);
392
    if (!rule_compare_item_lists (rec_suffix, non_rec_item)) {
393
	ntrans_destroy (&non_rec_translator);
394
	ntrans_destroy (&rec_translator);
395
	return (FALSE);
396
    }
397
    if (rec_suffix == rec_next) {
398
	ntrans_destroy (&non_rec_translator);
399
	ntrans_destroy (&rec_translator);
400
	rule_left_cycle_special_case_2 (rule, table, non_rec_alt, rec_alt,
401
					NIL (TypeTupleP), rec_suffix);
402
    } else {
403
	types_compute_param_from_trans (&param, &non_rec_translator,
404
					&rec_translator, rule_param (rule));
405
	ntrans_destroy (&non_rec_translator);
406
	ntrans_destroy (&rec_translator);
407
	rule_left_cycle_special_case_2 (rule, table, non_rec_alt, rec_alt,
408
					&param, rec_suffix);
409
    }
410
    return (TRUE);
411
}
412
 
413
static BoolT
414
rule_left_cycle_special_case PROTO_N ((rule, table))
415
			     PROTO_T (RuleP  rule X
416
				      TableP table)
417
{
418
    if (rule_has_empty_alt (rule)) {
419
	AltP  alt = rule_alt_head (rule);
420
	ItemP item;
421
 
422
	if ((alt == NIL (AltP)) || (alt_next (alt) != NIL (AltP))) {
423
	    return (FALSE);
424
	}
425
	item = alt_unlink_item_head (alt);
426
	alt_add_item (alt, item);
427
	return (TRUE);
428
    } else {
429
	return (rule_left_cycle_special_case_1 (rule, table));
430
    }
431
}
432
 
433
/*--------------------------------------------------------------------------*/
434
 
435
static BoolT
436
rule_check_non_locals PROTO_N ((this_rule, rule_list, real_size))
437
		      PROTO_T (RuleP    this_rule X
438
			       RuleP    rule_list X
439
			       unsigned real_size)
440
{
441
    NStringP scope  = rule_maximum_scope (this_rule);
442
    unsigned length = nstring_length (scope);
443
    RuleP    rule;
444
 
445
    for (rule = rule_list; rule; rule = rule_get_next_in_reverse_dfs (rule)) {
446
	KeyP key = entry_key (rule_entry (rule));
447
 
448
	if ((rule != this_rule) && key_is_string (key)) {
449
	    NStringP string = key_get_string (key);
450
 
451
	    if (!(nstring_is_prefix (string, scope) ||
452
		  (nstring_is_prefix (scope, string) &&
453
		   ((nstring_length (string) + 2) == length)))) {
454
		E_out_of_scope_non_local (this_rule, rule, rule_list);
455
		return (FALSE);
456
	    }
457
	}
458
    }
459
    if (non_local_list_is_empty (rule_non_locals (this_rule)) ||
460
	(real_size == 1)) {
461
	return (TRUE);
462
    } else {
463
	E_left_recursion_nl_entry (this_rule, rule_list);
464
	return (FALSE);
465
    }
466
}
467
 
468
static BoolT
469
rule_check_alt_cycle_types PROTO_N ((rule, rule_list, alt, need_check,
470
				     translator1, translator2, table,
471
				     generate_ref))
472
			   PROTO_T (RuleP       rule X
473
				    RuleP       rule_list X
474
				    AltP        alt X
475
				    BoolT       need_check X
476
				    TypeBTransP translator1 X
477
				    TypeBTransP translator2 X
478
				    TableP      table X
479
				    BoolP       generate_ref)
480
{
481
    ItemP item = alt_item_head (alt);
482
 
483
    item_translate_list (item, translator1);
484
    if (item_is_rule (item)) {
485
	RuleP item_rule = entry_get_rule (item_entry (item));
486
 
487
	if (rule_get_cycle_index (item_rule) != 0) {
488
	    TypeTupleT result_intersect;
489
 
490
	    if (need_check && (!types_equal_names (rule_param (rule),
491
						   item_param (item)))) {
492
		btrans_destroy (translator1);
493
		btrans_destroy (translator2);
494
		E_left_recursion_name_mismatch (rule_list);
495
		return (FALSE);
496
	    }
497
/* If a result identifier is returned by the left recursive call, it is
498
 * necessary to rename that return value, and use an identity afterwards to
499
 * rename it.
500
 **/
501
	    types_init (&result_intersect);
502
	    types_compute_intersection (&result_intersect, rule_result (rule),
503
					item_result (item));
504
	    if (!types_equal_zero_tuple (&result_intersect)) {
505
		EntryP      new_entry = table_add_rename (table);
506
		ItemP       new_item  = item_create (new_entry);
507
		TypeBTransT tmp_trans;
508
		TypeTupleT  tmp_tuple;
509
 
510
		btrans_init (&tmp_trans);
511
		types_copy (&tmp_tuple, &result_intersect);
512
		btrans_generate_names (&tmp_trans, &tmp_tuple, table);
513
		types_translate (&tmp_tuple, &tmp_trans);
514
		types_translate (item_result (item), &tmp_trans);
515
		btrans_destroy (&tmp_trans);
516
		types_assign (item_param (new_item), &tmp_tuple);
517
		types_assign (item_result (new_item), &result_intersect);
518
		item_set_next (new_item, item_next (item));
519
		item_set_next (item, new_item);
520
	    } else {
521
		types_destroy (&result_intersect);
522
	    }
523
	    if (*generate_ref) {
524
		btrans_generate_names (translator2, item_result (item),
525
				       table);
526
		*generate_ref = FALSE;
527
	    } else {
528
		btrans_regenerate_names (translator2, item_result (item));
529
	    }
530
	    types_translate (item_result (item), translator2);
531
	    item_translate_list (item_next (item), translator2);
532
	}
533
    }
534
    return (TRUE);
535
}
536
 
537
static BoolT
538
rule_check_cycle_types PROTO_N ((rule_list, predicate_id, real_size, table))
539
		       PROTO_T (RuleP    rule_list X
540
				EntryP   predicate_id X
541
				unsigned real_size X
542
				TableP   table)
543
{
544
    TypeTupleP  param    = rule_param (rule_list);
545
    TypeTupleP  result   = rule_result (rule_list);
546
    AltP        handler  = rule_get_handler (rule_list);
547
    BoolT       generate = TRUE;
548
    RuleP       rule;
549
    TypeBTransT translator1;
550
    TypeBTransT translator2;
551
 
552
    rule_renumber (rule_list, TRUE, predicate_id);
553
    if (!rule_check_non_locals (rule_list, rule_list, real_size)) {
554
	return (FALSE);
555
    }
556
    for (rule = rule_get_next_in_reverse_dfs (rule_list); rule;
557
	 rule = rule_get_next_in_reverse_dfs (rule)) {
558
	if (!((types_equal (param, rule_param (rule))) &&
559
	      (types_equal (result, rule_result (rule))))) {
560
	    E_left_recursion_type_mismatch (rule_list);
561
	    return (FALSE);
562
	}
563
	rule_renumber (rule, TRUE, predicate_id);
564
	if (!alt_equal (handler, rule_get_handler (rule))) {
565
	    E_left_rec_handler_mismatch (rule_list);
566
	    return (FALSE);
567
	}
568
	if (!rule_check_non_locals (rule, rule_list, real_size)) {
569
	    return (FALSE);
570
	}
571
    }
572
    btrans_init (&translator1);
573
    btrans_init (&translator2);
574
    for (rule = rule_list; rule; rule = rule_get_next_in_reverse_dfs (rule)) {
575
	AltP alt;
576
 
577
	if (rule == rule_list) {
578
	    btrans_generate_names (&translator1, rule_param (rule), table);
579
	} else {
580
	    btrans_regenerate_names (&translator1, rule_param (rule));
581
	}
582
	types_translate (rule_param (rule), &translator1);
583
	if ((alt = rule_get_handler (rule)) != NIL (AltP)) {
584
	    (void) rule_check_alt_cycle_types (rule, rule_list, alt, FALSE,
585
					       &translator1, &translator2,
586
					       table, &generate);
587
	}
588
	for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
589
	    if (!rule_check_alt_cycle_types (rule, rule_list, alt, TRUE,
590
					     &translator1, &translator2, table,
591
					     &generate)) {
592
		return (FALSE);
593
	    }
594
	}
595
    }
596
    btrans_destroy (&translator1);
597
    btrans_destroy (&translator2);
598
    return (TRUE);
599
}
600
 
601
static void
602
rule_compute_param_subset PROTO_N ((rule_list, subset))
603
			  PROTO_T (RuleP      rule_list X
604
				   TypeTupleP subset)
605
{
606
    RuleP rule;
607
 
608
    types_init (subset);
609
    for (rule = rule_list; rule; rule = rule_get_next_in_reverse_dfs (rule)) {
610
	TypeTupleP param = rule_param (rule);
611
	AltP       alt;
612
 
613
	for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
614
	    ItemP item = alt_item_head (alt);
615
 
616
	    if (item_is_rule (item)) {
617
		RuleP item_rule = entry_get_rule (item_entry (item));
618
 
619
		if (rule_get_cycle_index (item_rule) != 0) {
620
		    for (item = item_next (item); item;
621
			 item = item_next (item)) {
622
			types_compute_intersection (subset, param,
623
						    item_param (item));
624
		    }
625
		}
626
	    }
627
	}
628
    }
629
}
630
 
631
static void
632
rule_left_cycle_general_case_1 PROTO_N ((rule_list, size, matrix, vector,
633
					 table, gen_param, gen_result))
634
			       PROTO_T (RuleP        rule_list X
635
					unsigned     size X
636
					MatrixEntryP matrix X
637
					VectorEntryP vector X
638
					TableP       table X
639
					TypeTupleP   gen_param X
640
					TypeTupleP   gen_result)
641
{
642
    unsigned    i               = 0;
643
    BoolT       generate        = TRUE;
644
    BoolT       generate_param  = TRUE;
645
    BoolT       generate_result = TRUE;
646
    RuleP       rule;
647
    TypeBTransT translator;
648
    TypeBTransT tmp_trans;
649
    TypeTupleT  dummy;
650
    TypeTupleT  param_subset;
651
 
652
    btrans_init (&translator);
653
    rule_compute_param_subset (rule_list, &param_subset);
654
    btrans_init (&tmp_trans);
655
    types_copy (&dummy, &param_subset);
656
    btrans_generate_names (&tmp_trans, &dummy, table);
657
    types_translate (&dummy, &tmp_trans);
658
    btrans_destroy (&tmp_trans);
659
    for (rule = rule_list; rule;
660
	 rule = rule_get_next_in_reverse_dfs (rule), i ++) {
661
	AltP       alt = rule_alt_head (rule);
662
	AltP       handler;
663
	TypeTupleT old_result;
664
 
665
	types_copy (&old_result, rule_result (rule));
666
	if (generate) {
667
	    btrans_generate_names (&translator, rule_result (rule), table);
668
	    generate = FALSE;
669
	} else {
670
	    btrans_regenerate_names (&translator, rule_result (rule));
671
	}
672
	types_translate (rule_result (rule), &translator);
673
	if ((handler = rule_get_handler (rule)) != NIL (AltP)) {
674
	    ItemP handler_items = alt_item_head (handler);
675
 
676
	    item_translate_list (handler_items, &translator);
677
	}
678
	if (rule_has_empty_alt (rule)) {
679
	    vector [i].empty_alt = TRUE;
680
	}
681
	while (alt) {
682
	    ItemP    item    = alt_item_head (alt);
683
	    AltP     tmp_alt = alt;
684
	    RuleP    item_rule;
685
	    unsigned item_index;
686
 
687
	    alt = alt_next (alt);
688
	    if ((item_is_rule (item)) &&
689
		((item_rule = entry_get_rule (item_entry (item))),
690
		 ((item_index = rule_get_cycle_index (item_rule)) != 0))) {
691
		unsigned matrix_index = (size * (item_index - 1) + i);
692
 
693
		if (!(matrix [matrix_index].inited)) {
694
		    TypeTupleP param = &(matrix [matrix_index].param);
695
 
696
		    types_copy (param, &param_subset);
697
		    types_append_copy (param, &old_result);
698
		    matrix [matrix_index].inited = TRUE;
699
		}
700
		if (generate_param) {
701
		    ItemP item_head = alt_item_head (tmp_alt);
702
 
703
		    types_copy (gen_param, &param_subset);
704
		    types_append_copy (gen_param, item_result (item_head));
705
		    generate_param = FALSE;
706
		}
707
		(void) item_deallocate (alt_unlink_item_head (tmp_alt));
708
		alt_set_next (tmp_alt, matrix [matrix_index].alt);
709
		matrix [matrix_index].alt = tmp_alt;
710
	    } else {
711
		if (!(vector [i].inited)) {
712
		    TypeTupleP param = &(vector [i].param);
713
 
714
		    types_copy (param, &param_subset);
715
		    types_append_copy (param, &old_result);
716
		    vector [i].inited = TRUE;
717
		}
718
		if (generate_result) {
719
		    types_copy (gen_result, &dummy);
720
		    types_append_copy (gen_result, rule_result (rule));
721
		    generate_result = FALSE;
722
		}
723
		alt_set_next (tmp_alt, vector [i].alt);
724
		vector [i].alt = tmp_alt;
725
	    }
726
	}
727
	rule_reinit (rule);
728
	types_destroy (&old_result);
729
    }
730
    types_destroy (&param_subset);
731
    btrans_destroy (&translator);
732
}
733
 
734
static BoolT
735
rule_left_cycle_general_case_2 PROTO_N ((rule_list, size, vector))
736
			       PROTO_T (RuleP        rule_list X
737
					unsigned     size X
738
					VectorEntryP vector)
739
{
740
    BoolT    not_found = TRUE;
741
    unsigned i;
742
 
743
    for (i = 0; i < size; i ++) {
744
	if ((vector [i].empty_alt) || (vector [i].alt)) {
745
	    not_found = FALSE;
746
	}
747
    }
748
    if (not_found) {
749
	E_cycle_no_terminator (rule_list);
750
	return (FALSE);
751
    }
752
    return (TRUE);
753
}
754
 
755
static void
756
rule_left_cycle_general_case_3 PROTO_N ((rule, size, vector, table,
757
					 new_rule_list_tail, param, result))
758
			       PROTO_T (RuleP        rule X
759
					unsigned     size X
760
					VectorEntryP vector X
761
					TableP       table X
762
					RuleP       *new_rule_list_tail X
763
					TypeTupleP   param X
764
					TypeTupleP   result)
765
{
766
    unsigned j;
767
 
768
    for (j = 0; j < size; j ++) {
769
	EntryP entry    = table_add_generated_rule (table, TRUE);
770
	RuleP  new_rule = entry_get_rule (entry);
771
	AltP   alt;
772
 
773
	types_copy (rule_param (new_rule), param);
774
	types_copy (rule_result (new_rule), result);
775
	*new_rule_list_tail = new_rule;
776
	new_rule_list_tail  = rule_next_in_reverse_dfs_ref (new_rule);
777
	if (vector [j].empty_alt) {
778
	    AltP  new_alt  = alt_create ();
779
	    ItemP new_item = item_create (entry);
780
 
781
	    types_copy (item_param (new_item), &(vector [j].param));
782
	    types_copy (item_result (new_item), result);
783
	    alt_add_item (new_alt, new_item);
784
	    rule_add_alt (rule, new_alt);
785
	}
786
	for (alt = vector [j].alt; alt; alt = alt_next (alt)) {
787
	    AltP  new_alt  = alt_duplicate (alt);
788
	    ItemP new_item = item_create (entry);
789
 
790
	    types_copy (item_param (new_item), &(vector [j].param));
791
	    types_copy (item_result (new_item), result);
792
	    alt_add_item (new_alt, new_item);
793
	    rule_add_alt (rule, new_alt);
794
	}
795
    }
796
}
797
 
798
static void
799
rule_left_cycle_general_case_4 PROTO_N ((new_rule_list, i, size, matrix,
800
					 table))
801
			       PROTO_T (RuleP        new_rule_list X
802
					unsigned     i X
803
					unsigned     size X
804
					MatrixEntryP matrix X
805
					TableP       table)
806
{
807
    unsigned j;
808
    RuleP    rule;
809
 
810
    for (rule = new_rule_list, j = 0; j < size;
811
	 rule = rule_get_next_in_reverse_dfs (rule), j ++) {
812
	RuleP    inner_rule;
813
	unsigned k = 0;
814
 
815
	if (i == j) {
816
	    if (types_equal_zero_tuple (rule_param (rule))) {
817
		rule_add_empty_alt (rule);
818
	    } else {
819
		AltP   new_alt  = alt_create ();
820
		EntryP entry    = table_add_rename (table);
821
		ItemP  new_item = item_create (entry);
822
 
823
		types_copy (item_param (new_item), rule_param (rule));
824
		types_copy (item_result (new_item), rule_result (rule));
825
		alt_add_item (new_alt, new_item);
826
		rule_add_alt (rule, new_alt);
827
	    }
828
	}
829
	for (inner_rule = new_rule_list; inner_rule;
830
	     inner_rule = rule_get_next_in_reverse_dfs (inner_rule), k ++) {
831
	    AltP alt;
832
 
833
	    for (alt = matrix [k].alt; alt; alt = alt_next (alt)) {
834
		AltP  new_alt  = alt_duplicate (alt);
835
		ItemP new_item = item_create (rule_entry (inner_rule));
836
 
837
		types_copy (item_param (new_item), &(matrix [k].param));
838
		types_copy (item_result (new_item), rule_result (rule));
839
		alt_add_item (new_alt, new_item);
840
		rule_add_alt (rule, new_alt);
841
	    }
842
	}
843
    }
844
}
845
 
846
static void
847
rule_left_cycle_general_case PROTO_N ((rule_list, size, table))
848
			     PROTO_T (RuleP    rule_list X
849
				      unsigned size X
850
				      TableP   table)
851
{
852
    unsigned     matrix_size = (size * size);
853
    MatrixEntryP matrix      = rule_left_cycle_matrix (matrix_size);
854
    VectorEntryP vector      = rule_left_cycle_vector (size);
855
    TypeTupleT   param;
856
    TypeTupleT   result;
857
 
858
    rule_left_cycle_general_case_1 (rule_list, size, matrix, vector, table,
859
				    &param, &result);
860
    if (rule_left_cycle_general_case_2 (rule_list, size, vector)) {
861
	unsigned i = 0;
862
	RuleP    rule;
863
 
864
	for (rule = rule_list; rule;
865
	     rule = rule_get_next_in_reverse_dfs (rule), i ++) {
866
	    RuleP new_rule_list;
867
 
868
	    rule_left_cycle_general_case_3 (rule, size, vector, table,
869
					    &new_rule_list, &param, &result);
870
	    rule_left_cycle_general_case_4 (new_rule_list, i, size, matrix,
871
					    table);
872
	}
873
    }
874
    types_destroy (&param);
875
    types_destroy (&result);
876
    rule_destroy_cycle_matrix (matrix, matrix_size);
877
    rule_destroy_cycle_vector (vector, size);
878
}
879
 
880
/*--------------------------------------------------------------------------*/
881
 
882
void
883
rule_remove_left_cycle PROTO_N ((rule_list, predicate_id, table))
884
		       PROTO_T (RuleP  rule_list X
885
				EntryP predicate_id X
886
				TableP table)
887
{
888
    unsigned size      = 0;
889
    unsigned real_size = 0;
890
    RuleP    rule;
891
 
892
    for (rule = rule_list; rule; rule = rule_get_next_in_reverse_dfs (rule)) {
893
	size ++;
894
	if (key_is_string (entry_key (rule_entry (rule)))) {
895
	    real_size ++;
896
	}
897
	rule_set_cycle_index (rule, size);
898
    }
899
    if (((size != 1) || (!rule_left_cycle_special_case (rule_list, table))) &&
900
	(rule_check_cycle_types (rule_list, predicate_id, real_size, table))) {
901
	rule_left_cycle_general_case (rule_list, size, table);
902
    }
903
    for (rule = rule_list; rule; rule = rule_get_next_in_reverse_dfs (rule)) {
904
	rule_reset_cycle_index (rule);
905
	rule_no_cycles (rule);
906
    }
907
}
908
 
909
/*
910
 * Local variables(smf):
911
 * eval: (include::add-path-entry "../os-interface" "../library")
912
 * eval: (include::add-path-entry "../generated")
913
 * end:
914
**/