Пример #1
0
static void
expand_g(Graph *g)
{	Node *now, *n1, *n2, *nx;
	int can_release;

	if (!g->New)
	{	Debug2("\nDone with %s", g->name->name);
		if (tl_verbose) dump_graph(g);
		if (not_new(g))
		{	if (tl_verbose) printf("\tIs Not New\n");
			return;
		}
		if (g->Next)
		{	Debug("	Has Next [");
			for (n1 = g->Next; n1; n1 = n1->nxt)
			{ Dump(n1); Debug(", "); }
			Debug("]\n");

			ng(ZS, getsym(g->name), g->Next, ZN, ZN);
		}
		return;
	}

	if (tl_verbose)
	{	Symbol *z;
		printf("\nExpand %s, from ", g->name->name);
		for (z = g->incoming; z; z = z->next)
			printf("%s, ", z->name);
		printf("\n\thandle:\t"); Explain(g->New->ntyp);
		dump_graph(g);
	}

	if (g->New->ntyp == AND)
	{	if (g->New->nxt)
		{	n2 = g->New->rgt;
			while (n2->nxt)
				n2 = n2->nxt;
			n2->nxt = g->New->nxt;
		}
		n1 = n2 = g->New->lft;
		while (n2->nxt)
			n2 = n2->nxt;
		n2->nxt = g->New->rgt;

		releasenode(0, g->New);

		g->New = n1;
		push_stack(g);
		return;
	}

	can_release = 0;	/* unless it need not go into Old */
	now = g->New;
	g->New = g->New->nxt;
	now->nxt = ZN;

	if (now->ntyp != TRUE)
	{	if (g->Old)
		{	for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
				if (isequal(now, n1))
				{	can_release = 1;
					goto out;
				}
			n1->nxt = now;
		} else
			g->Old = now;
	}
out:
	switch (now->ntyp) {
	case FALSE:
		push_stack(g);
		break;
	case TRUE:
		releasenode(1, now);
		push_stack(g);
		break;
	case PREDICATE:
	case NOT:
		if (can_release) releasenode(1, now);
		push_stack(g);
		break;
	case V_OPER:
		Assert(now->rgt != ZN, now->ntyp);
		Assert(now->lft != ZN, now->ntyp);
		Assert(now->rgt->nxt == ZN, now->ntyp);
		Assert(now->lft->nxt == ZN, now->ntyp);
		n1 = now->rgt;
		n1->nxt = g->New;

		if (can_release)
			nx = now;
		else
			nx = getnode(now); /* now also appears in Old */
		nx->nxt = g->Next;

		n2 = now->lft;
		n2->nxt = getnode(now->rgt);
		n2->nxt->nxt = g->New;
		g->New = flatten(n2);
		push_stack(g);
		ng(ZS, g->incoming, n1, g->Old, nx);
		break;

	case U_OPER:
		Assert(now->rgt->nxt == ZN, now->ntyp);
		Assert(now->lft->nxt == ZN, now->ntyp);
		n1 = now->lft;

		if (can_release)
			nx = now;
		else
			nx = getnode(now); /* now also appears in Old */
		nx->nxt = g->Next;

		n2 = now->rgt;
		n2->nxt = g->New;

		goto common;

#ifdef NXT
	case NEXT:
		Assert(now->lft != ZN, now->ntyp);
		nx = dupnode(now->lft);
		nx->nxt = g->Next;
		g->Next = nx;
		if (can_release) releasenode(0, now);
		push_stack(g);
		break;
#endif

	case OR:
		Assert(now->rgt->nxt == ZN, now->ntyp);
		Assert(now->lft->nxt == ZN, now->ntyp);
		n1 = now->lft;
		nx = g->Next;

		n2 = now->rgt;
		n2->nxt = g->New;
common:
		n1->nxt = g->New;

		ng(ZS, g->incoming, n1, g->Old, nx);
		g->New = flatten(n2);

		if (can_release) releasenode(1, now);

		push_stack(g);
		break;
	}
}
Пример #2
0
// Apply DeMorgan's law to push the NOT node if it is found above an AND or an OR node.
// Return TRUE when a NOT node is pushed down else return FALSE.
int push_down_NOT(syntree *arg, List *del_node_list)
{
    syntree *NOT_A_node, *NOT_B_node, *A_node, *B_node;
    syntree *node_to_be_del;

    ASSERT(arg);
    ASSERT(arg->type == NOT_TYPE);
    ASSERT(arg->left_tree);
    ASSERT(arg->right_tree == NULL);

    if (arg->left_tree->type == AND_TYPE)
    {
        // NOT above AND. Apply DeMorgan's Law
        // NOT(A AND B) -> NOT(A) OR NOT(B)

        A_node = arg->left_tree->left_tree;
        B_node = arg->left_tree->right_tree;
        // Add the unwanted AND node to the list of nodes to be deleted.
        node_to_be_del = arg->left_tree;
        List_insertElement(del_node_list, node_to_be_del);

        // Create the NOT(A) subtree.
        NOT_A_node = not_new(A_node);

        // Create the NOT(B) subtree.
        NOT_B_node = not_new(B_node);

        // Convert the root NOT node to an OR node and create the (NOT(A) OR NOT(B)) tree.
        arg->type = OR_TYPE;
        arg->left_tree = NOT_A_node;
        arg->right_tree = NOT_B_node;

        return TRUE;
    }
    else if (arg->left_tree->type == OR_TYPE)
    {
        // NOT above OR. Apply DeMorgan's Law
        // NOT(A OR B) -> NOT(A) AND NOT(B)

        A_node = arg->left_tree->left_tree;
        B_node = arg->left_tree->right_tree;
        // Add the unwanted OR node to the list of nodes to be deleted.
        node_to_be_del = arg->left_tree;
        List_insertElement(del_node_list, node_to_be_del);

        // Create the NOT(A) subtree.
        NOT_A_node = not_new(A_node);

        // Create the NOT(B) subtree.
        NOT_B_node = not_new(B_node);

        // Convert the root NOT node to an AND node and create the (NOT(A) AND NOT(B)) tree.
        arg->type = AND_TYPE;
        arg->left_tree = NOT_A_node;
        arg->right_tree = NOT_B_node;

        return TRUE;
    }
    else
    {
        // No need to push down the NOT node
        return FALSE;
    }

}