char rcsid_closure[] = "$Id$";

#include <stdio.h>
#include "b.h"

int prevent_divergence = 0;

List chainrules;

void
findChainRules()
{
	List pl;

	assert(!chainrules);

	for (pl = rules; pl; pl = pl->next) {
		Rule p = (Rule) pl->x;
		if (!p->pat->op) {
			chainrules = newList(p, chainrules);
		} else {
			p->pat->op->table->rules = newList(p, p->pat->op->table->rules);
			addRelevant(p->pat->op->table->relevant, p->lhs->num);
		}
	}
}

void
zero(t) Item_Set t;
{
	int i;
	DeltaCost base;
	int exists;
	int base_nt = 0;

	assert(!t->closed);

	ZEROCOST(base);
	exists = 0;
	for (i = 0; i < max_nonterminal; i++) {
		if (t->virgin[i].rule) {
			if (exists) {
				if (LESSCOST(t->virgin[i].delta, base)) {
					ASSIGNCOST(base, t->virgin[i].delta);
					base_nt = i;
				}
			} else {
				ASSIGNCOST(base, t->virgin[i].delta);
				exists = 1;
				base_nt = i;
			}
		}
	}
	if (!exists) {
		return;
	}
	for (i = 0; i < max_nonterminal; i++) {
		if (t->virgin[i].rule) {
			MINUSCOST(t->virgin[i].delta, base);
		}
		NODIVERGE(t->virgin[i].delta, t, i, base_nt);
	}
}

void
closure(t) Item_Set t;
{
	int changes;
	List pl;

	assert(!t->closed);
	t->closed = itemArrayCopy(t->virgin);

	changes = 1;
	while (changes) {
		changes = 0;
		for (pl = chainrules; pl; pl = pl->next) {
			Rule p = (Rule) pl->x;
			register Item *rhs_item = &t->closed[p->pat->children[0]->num];

			if (rhs_item->rule) {	/* rhs is active */
				DeltaCost dc;
				register Item *lhs_item = &t->closed[p->lhs->num];

				ASSIGNCOST(dc, rhs_item->delta);
				ADDCOST(dc, p->delta);
				if (LESSCOST(dc, lhs_item->delta) || !lhs_item->rule) {
					ASSIGNCOST(lhs_item->delta, dc);
					lhs_item->rule = p;
					changes = 1;
				}
			}
		}
	}
}
