Пример #1
0
tree *delete_tree(tree *t, int k) {
    tree * x = Descend(t, k);
    if (x == NULL)
        printf("lol1\n");

    if (x->left == NULL && x->right == NULL)
        t = ReplaceNode(t, x, NULL);

    else if (x->left == NULL)
        t = ReplaceNode(t, x, x->right);

    else if (x->right == NULL)
        t = ReplaceNode(t, x, x->left);

    else {
        tree * y = succ(x);
        t = ReplaceNode(t, y, y->right);
        x->left->parent = y;
        y->left = x->left;

        if (x->right != NULL)
            x->right->parent = y;

        y->right = x->right;
        t = ReplaceNode(t, x, y);
        //y->count = x->count;
    }
    free(x->word);
    free(x);
    return t;
}
/*
 * Elimina un nodo del árbol.
 */
void DeleteString(int p) {
  int  replacement;
  /* Si el nodo a borrar no está en el árbol, no hacemos nada. */
  if ( tree[ p ].parent == UNUSED )
    return;
  /* Si el nodo a borrar sólo tiene un hijo, hacemos una contracción
     del árbol. */
  if ( tree[ p ].larger_child == UNUSED )
    ContractNode( p, tree[ p ].smaller_child );
  else if ( tree[ p ].smaller_child == UNUSED )
    ContractNode( p, tree[ p ].larger_child );
  /* Si el nodo a borrar tiene ambos descendientes. */
  else {
    /* Localizamos el siguiente nodo más pequeño que el nodo que
       intentamos borrar. */
    replacement = FindNextNode( p );
    /* Eliminaos el siguiente nodo más pequeño del árbol. Nótese que
       el nodo "replacemente" nunca va a tener los dos descendientes,
       lo que evita entrar en más de un nivel de recursión. */
    DeleteString( replacement );
    /* Sustituimos el nodo que estamos intentanbo borrar por el que
       acabamos de localizar y eliminar el árbol. */
    ReplaceNode( p, replacement );
  }
}
Пример #3
0
/*
 *  Play the "animal" game, in which the program attempts to guess an animal
 *  that the user is thinking of by asking yes or no questions. Eventually,
 *  the program either will guess the user's animal or run out of questions
 *  to ask. In the latter case, the program will ask the user to provide a
 *  yes-or-no question that would distinguish between the user's animal and
 *  the program's best guess.
 *  The data structure of questions and guesses is essentially a binary tree,
 *  with each internal node having a "yes" branch and a "no" branch. Leaves
 *  of the tree represent animals to be guessed by the program. If the program
 *  fails to guess the user's animal, it replaces one of the leaves of the tree
 *  by a node containing the new question, whose children are the program's
 *  best guess and the animal provided by the user.
 *  The structure of the program is simple. It initializes the question/guess
 *  data structure, then plays games as long as the user is interested. In each
 *  game, the program starts at the top of the tree (the root) and progresses
 *  toward the bottom (the leaves) depending on the user's responses. Once it
 *  reaches a leaf, it either has won or lost, and handles the situation as
 *  described above.
 */
int main () {
    TreeType tree;
    PositionType pos;
    char *newQuestion, *newAnswer;
    tree = InitTree ();

    // unitTest();
    printf("%s", "Think of an animal. I will try to guess what it is.\n"
         "Please answer my questions with yes or no.\n");

    while (TRUE) {
        pos = Top (tree);
        while (!IsLeaf (tree, pos)) {
            pos = Answer (Question (tree, pos))?
            YesNode (tree, pos): NoNode (tree, pos);
        }
        if (Answer (Guess (tree, pos))) {
            printf ("I got it right!\n");
        } else {
            GetNewInfo (tree, pos, &newAnswer, &newQuestion);
            ReplaceNode (tree, pos, newAnswer, newQuestion);
        }
        if (!Answer ("Want to play again? ")) {
            exit (0);
        }
    }
    return 0;
}
Пример #4
0
/*
 *  Play the "animal" game, in which the program attempts to guess an animal
 *  that the user is thinking of by asking yes or no questions. Eventually,
 *  the program either will guess the user's animal or run out of questions
 *  to ask. In the latter case, the program will ask the user to provide a
 *  yes-or-no question that would distinguish between the user's animal and
 *  the program's best guess.
 *  The data structure of questions and guesses is essentially a binary tree,
 *  with each internal node having a "yes" branch and a "no" branch. Leaves
 *  of the tree represent animals to be guessed by the program. If the program
 *  fails to guess the user's animal, it replaces one of the leaves of the tree
 *  by a node containing the new question, whose children are the program's
 *  best guess and the animal provided by the user.
 *  The structure of the program is simple. It initializes the question/guess
 *  data structure, then plays games as long as the user is interested. In each
 *  game, the program starts at the top of the tree (the root) and progresses
 *  toward the bottom (the leaves) depending on the user's responses. Once it
 *  reaches a leaf, it either has won or lost, and handles the situation as
 *  described above.
 */
int main (int argc, char *argv[])
{
    char *treefile = NULL;
    TreeType tree;
    PositionType pos;
    char *newQuestion, *newAnswer;

    if (argc > 1) {
        treefile = argv[1];
    }
    tree = InitTree (treefile);

    printf("%s", "Think of an animal. I will try to guess what it is.\n"
		 "Please answer my questions with yes or no.\n");

    while (TRUE) {
        pos = Top (tree);
        while (!IsLeaf (tree, pos)) {
            pos = Answer(Question(tree,pos))? 
	       YesNode(tree,pos): NoNode(tree,pos);
        }
        if (Answer (Guess (tree, pos))) {
            printf ("I got it right!\n");
        } else {
            GetNewInfo (tree, pos, &newAnswer, &newQuestion);
            ReplaceNode (tree, pos, newAnswer, newQuestion);
        }

        if (!Answer ("Want to play again? ")) {
            WriteTree(tree, treefile);
            exit (0);
        }
    }
}
Пример #5
0
	void APICALL DOMParserImpl::ParseWithSpecificAction( const char * buffer, sizet bufferLength, eActionType actionType, spINode & node ) {
		auto parsedNode = ParseAsNode( buffer, bufferLength );

		if ( parsedNode ) {
			switch ( actionType ) {
			case kATAppendAsChildren:
				AppendAsChildren( node, parsedNode );
				break;

			case kATReplaceChildren:
				ReplaceChildren( node, parsedNode );
				break;

			case kATAppendOrReplaceChildren:
				AppendOrReplaceChildren( node, parsedNode );
				break;

			case kATInsertBefore:
				InsertBefore( node, parsedNode );
				break;

			case kATInsertAfter:
				InsertAfter( node, parsedNode );
				break;

			case kATReplace:
				ReplaceNode( node, parsedNode );
				break;

			default:
				NOTIFY_ERROR( IError::kEDGeneral, kGECNotImplemented, "Not yet implemented", IError::kESOperationFatal, true, static_cast< sizet >( actionType ) );
			}

		}
	}
Пример #6
0
void RedBlackTree::RotateRight(RBNode* node)
{
	RBNode* l = node->left;
	ReplaceNode(node, l);
	node->parent = l;
	node->left = l->right;
	l->right = node;
}
Пример #7
0
void RedBlackTree::RotateLeft(RBNode* node)
{
	RBNode* r = node->right;
	ReplaceNode(node, r);
	node->parent = r;
	node->right = r->right;
	r->left = node;
}
/*
 * Esta rutina inserta un nuevo nodo al árbol binario y encuentra
 * (retornando) la mejor ocurrencia de la cadena buscada.
 */
int AddString(int new_node, int *match_position) {
  int i;
  int test_node;
  int delta;
  int match_length;
  int *child;
  
  /* Estamos insertando el símbolo END_OF_STREAM? */
  if ( new_node == END_OF_STREAM )
    return 0;
  /* Accedemos a la raíz del árbol y de ahí al primer nodo con datos
     almacenado. */
  test_node = tree[ TREE_ROOT ].larger_child;
  /* La longitud de la cadena encontrada es todavía, 0. */
  match_length = 0;
  for ( ; ; ) {
    /* "i" contiene el "match_length" actual. */
    for ( i = 0 ; i < LOOK_AHEAD_SIZE ; i++ ) {
      /* "delta" < 1 si la cadena almacenada en "new_node" es menor
	 que la de "test_node", "delta" = 0 si son iguales y "delta" >
	 1 si la cadena en "nee_node" es mayor que la de
	 "test_node". */
      delta = window[ MOD_WINDOW( new_node + i ) ] -
	window[ MOD_WINDOW( test_node + i ) ];
      if ( delta != 0 )
	break;
    }
    /* Si hemos encontrado una cadena más larga. */
    if ( i >= match_length ) {
      match_length = i;
      *match_position = test_node;
      /* Si hemos encontrado todo el buffer de anticipación en el
	 diccionario (ya no es posible buscar una cadena más
	 larga). */
      if ( match_length >= LOOK_AHEAD_SIZE ) {
	/* "new_node" reemplaza a "test_node" para manterner el árbol
	   lo más pequeño posible, sin afectar a la tasa de
	   compresión. */
	ReplaceNode( test_node, new_node );
	return  match_length;
      }
    }
    /* Navegación binaria sobre el árbol. */
    if ( delta >= 0 )
      child = &tree[ test_node ].larger_child;
    else
      child = &tree[ test_node ].smaller_child;
    if ( *child == UNUSED ) {
      *child = new_node;
      tree[ new_node ].parent = test_node;
      tree[ new_node ].larger_child = UNUSED;
      tree[ new_node ].smaller_child = UNUSED;
      return match_length;
    }
    test_node = *child;
  }
}
Пример #9
0
static void SwapNodes( ubi_btRootPtr RootPtr,
                       ubi_btNodePtr Node1,
                       ubi_btNodePtr Node2 )
/* ------------------------------------------------------------------------ **
 * This function swaps two nodes in the tree.  Node1 will take the place of
 * Node2, and Node2 will fill in the space left vacant by Node 1.
 *
 * Input:
 *  RootPtr  - pointer to the tree header structure for this tree.
 *  Node1    - \
 *              > These are the two nodes which are to be swapped.
 *  Node2    - /
 *
 * Notes:
 *  This function does a three step swap, using a dummy node as a place
 *  holder.  This function is used by ubi_btRemove().
 * ------------------------------------------------------------------------ **
 */
{
    ubi_btNodePtr *Parent;
    ubi_btNode     dummy;
    ubi_btNodePtr  dummy_p = &dummy;

    /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */
    if( NULL != Node1->Link[ubi_trPARENT] )
        Parent = &((Node1->Link[ubi_trPARENT])->Link[(int)(Node1->gender)]);
    else
        Parent = &(RootPtr->root);
    ReplaceNode( Parent, Node1, dummy_p );

    /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */
    if( NULL != Node2->Link[ubi_trPARENT] )
        Parent = &((Node2->Link[ubi_trPARENT])->Link[(int)(Node2->gender)]);
    else
        Parent = &(RootPtr->root);
    ReplaceNode( Parent, Node2, Node1 );

    /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */
    if( NULL != dummy_p->Link[ubi_trPARENT] )
        Parent = &((dummy_p->Link[ubi_trPARENT])->Link[(int)(dummy_p->gender)]);
    else
        Parent = &(RootPtr->root);
    ReplaceNode( Parent, dummy_p, Node2 );
} /* SwapNodes */
Пример #10
0
void Interpose(OBJECT z, int typ, OBJECT x, OBJECT y)
{ OBJECT encl;
  New(encl, typ);
  FposCopy(fpos(encl), fpos(y));
  ReplaceNode(encl, z);  Link(encl, z);
  back(encl, COLM) = back(x, COLM);
  fwd(encl, COLM) = fwd(x, COLM);
  back(encl, ROWM) = back(y, ROWM);
  fwd(encl, ROWM) = fwd(y, ROWM);
  underline(encl) = underline(z);
} /* end Interpose */
Пример #11
0
static OBJECT InterposeWideOrHigh(OBJECT y, int dim)
{ OBJECT res;
  New(res, dim == COLM ? WIDE : HIGH);
  FposCopy(fpos(res), fpos(y));
  back(res, dim) = back(y, dim);
  fwd(res, dim)  = fwd(y, dim);
  back(res, 1-dim) = back(y, 1-dim);
  fwd(res, 1-dim)  = fwd(y, 1-dim);
  SetConstraint(constraint(res), MAX_FULL_LENGTH, size(res, dim), MAX_FULL_LENGTH);
  ReplaceNode(res, y);
  Link(res, y);
  return res;
} /* end InterposeWideOrHigh */
Пример #12
0
int AddString ( int new_node, int *match_pos)
{
	int i;
	int test_node;
	int delta;
	int match_len;
	int *child;
	
	if (new_node == END_OF_STREAM)
		return (0);
	
	test_node = tree [TREE_ROOT].larger_child;
	match_len = 0;
	
	for (;;)
	{
		for ( i = 0; i < LOOK_AHEAD_SIZE; i++)
		{
			delta = window [MODULO (new_node + i)] -
				window [MODULO (test_node + i)];
			if (delta != 0)
				break;
		}
		
		if (i >= match_len)
		{
			match_len = i;
			*match_pos = test_node;
			if (match_len >= LOOK_AHEAD_SIZE)
			{
				ReplaceNode ( test_node, new_node);
				return match_len;
			}
		}
		
		if (delta >= 0)
			child = &tree [test_node].larger_child;
		else
			child = &tree [test_node].smaller_child;
		
		if (*child == UNUSED)
		{
			*child = new_node;
			tree [new_node].parent = test_node;
			tree [new_node].larger_child = UNUSED;
			tree [new_node].smaller_child = UNUSED;
			return match_len;
		}
		test_node = *child;
	}
}
Пример #13
0
void unitTest() {
    TreeType tree = InitTree();
    printf("After initlizing tree:\n");
    PrintTree(tree);
    PositionType question = 0;
    PositionType answer = 5;
    printf("IsLeaf test 1: %s\n", IsLeaf(tree, question) ? "error" : "pass");
    printf("IsLeaf test 2: %s\n", IsLeaf(tree, answer) ? "pass" : "error");
    printf("Top test: %s\n", Top(tree) == 0 ? "pass" : "error");
    printf("Question test 1: %s\n", strcmp(Question(tree, question), "Is it furry?") == 0 ? "pass" : "error");
    printf("Question test 2: %s\n", strcmp(Question(tree, answer), "Is it a lizard?") == 0 ? "pass" : "error");
    printf("%s\n", Question(tree, answer));
    ReplaceNode(tree, 7, "a kitten", "Is it an adult?");
    PrintTree(tree);
}
Пример #14
0
//----------------------------------------------------------------------------
// Удаление строки из двоичного дерева поиска 
void DeleteString ( int p)
{
  int replacement;

  if (tree [p].parent == UNUSED)
    return;
  if (tree [p].larger_child == UNUSED)
    ContractNode ( p, tree [p].smaller_child);
  else
    if (tree [p].smaller_child == UNUSED)
      ContractNode ( p, tree [p].larger_child);
    else
    {
      replacement = FindNextNode (p);
      DeleteString (replacement);
      ReplaceNode ( p, replacement);
    }
}
Пример #15
0
static OBJECT InterposeScale(OBJECT y, int scale_factor, int dim)
{ OBJECT res;
  New(res, SCALE);
  FposCopy(fpos(res), fpos(y));
  if( dim == COLM )
  { bc(constraint(res)) = scale_factor;
    fc(constraint(res)) = 1 * SF;
  }
  else
  { bc(constraint(res)) = 1 * SF;
    fc(constraint(res)) = scale_factor;
  }
  back(res, dim) = (back(y, dim) * scale_factor) / SF;
  fwd(res, dim)  = (fwd(y, dim) * scale_factor) / SF;
  back(res, 1-dim) = back(y, 1-dim);
  fwd(res, 1-dim)  = fwd(y, 1-dim);
  ReplaceNode(res, y);
  Link(res, y);
  return res;
} /* end InterposeScale */
Пример #16
0
ubi_trBool ubi_btInsert( ubi_btRootPtr  RootPtr,
                         ubi_btNodePtr  NewNode,
                         ubi_btItemPtr  ItemPtr,
                         ubi_btNodePtr *OldNode )
/* ------------------------------------------------------------------------ **
 * This function uses a non-recursive algorithm to add a new element to the
 * tree.
 *
 *  Input:   RootPtr  -  a pointer to the ubi_btRoot structure that indicates
 *                       the root of the tree to which NewNode is to be added.
 *           NewNode  -  a pointer to an ubi_btNode structure that is NOT
 *                       part of any tree.
 *           ItemPtr  -  A pointer to the sort key that is stored within
 *                       *NewNode.  ItemPtr MUST point to information stored
 *                       in *NewNode or an EXACT DUPLICATE.  The key data
 *                       indicated by ItemPtr is used to place the new node
 *                       into the tree.
 *           OldNode  -  a pointer to an ubi_btNodePtr.  When searching
 *                       the tree, a duplicate node may be found.  If
 *                       duplicates are allowed, then the new node will
 *                       be simply placed into the tree.  If duplicates
 *                       are not allowed, however, then one of two things
 *                       may happen.
 *                       1) if overwritting *is not* allowed, this
 *                          function will return FALSE (indicating that
 *                          the new node could not be inserted), and
 *                          *OldNode will point to the duplicate that is
 *                          still in the tree.
 *                       2) if overwritting *is* allowed, then this
 *                          function will swap **OldNode for *NewNode.
 *                          In this case, *OldNode will point to the node
 *                          that was removed (thus allowing you to free
 *                          the node).
 *                          **  If you are using overwrite mode, ALWAYS  **
 *                          ** check the return value of this parameter! **
 *                 Note: You may pass NULL in this parameter, the
 *                       function knows how to cope.  If you do this,
 *                       however, there will be no way to return a
 *                       pointer to an old (ie. replaced) node (which is
 *                       a problem if you are using overwrite mode).
 *
 *  Output:  a boolean value indicating success or failure.  The function
 *           will return FALSE if the node could not be added to the tree.
 *           Such failure will only occur if duplicates are not allowed,
 *           nodes cannot be overwritten, AND a duplicate key was found
 *           within the tree.
 * ------------------------------------------------------------------------ **
 */
{
    ubi_btNodePtr OtherP,
                  parent = NULL;
    char          tmp;

    if( NULL == OldNode ) /* If they didn't give us a pointer, supply our own.  */
        OldNode = &OtherP;

    (void)ubi_btInitNode( NewNode );     /* Init the new node's BinTree fields. */

    /* Find a place for the new node. */
    *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp));

    /* Now add the node to the tree... */
    if( NULL == (*OldNode) )  /* The easy one: we have a space for a new node!  */
    {
        if( NULL == parent )
            RootPtr->root = NewNode;
        else
        {
            parent->Link[(int)tmp]      = NewNode;
            NewNode->Link[ubi_trPARENT] = parent;
            NewNode->gender             = tmp;
        }
        (RootPtr->count)++;
        return( ubi_trTRUE );
    }

    /* If we reach this point, we know that a duplicate node exists.  This
     * section adds the node to the tree if duplicate keys are allowed.
     */
    if( ubi_trDups_OK(RootPtr) )    /* Key exists, add duplicate */
    {
        ubi_btNodePtr q;

        tmp = ubi_trRIGHT;
        q = (*OldNode);
        *OldNode = NULL;
        while( NULL != q )
        {
            parent = q;
            if( tmp == ubi_trEQUAL )
                tmp = ubi_trRIGHT;
            q = q->Link[(int)tmp];
            if ( q )
                tmp = ubi_trAbNormal( (*(RootPtr->cmp))(ItemPtr, q) );
        }
        parent->Link[(int)tmp]       = NewNode;
        NewNode->Link[ubi_trPARENT]  = parent;
        NewNode->gender              = tmp;
        (RootPtr->count)++;
        return( ubi_trTRUE );
    }

    /* If we get to *this* point, we know that we are not allowed to have
     * duplicate nodes, but our node keys match, so... may we replace the
     * old one?
     */
    if( ubi_trOvwt_OK(RootPtr) )    /* Key exists, we replace */
    {
        if( NULL == parent )
            ReplaceNode( &(RootPtr->root), *OldNode, NewNode );
        else
            ReplaceNode( &(parent->Link[(int)((*OldNode)->gender)]),
                         *OldNode, NewNode );
        return( ubi_trTRUE );
    }

    return( ubi_trFALSE );      /* Failure: could not replace an existing node. */
} /* ubi_btInsert */
Пример #17
0
void CChildView::ReplaceSelectedWithType(NodeType Type)
{
	std::vector<CNodeBase*> newSelected;

	PrintOut(_T("Replace Node Type %Ts"), NodeTypeToString(Type));

	for (UINT i = 0; i < Selected.size(); i++)
	{
		if (!theApp.IsNodeValid(Selected[i].object))
			continue;
		if (Selected[i].object->pParent->GetType() == nt_vtable)
			Type = nt_function;

		CNodeBase* pNewNode = theApp.CreateNewNode(Type);

		if (Type == nt_class)	MakeBasicClass((CNodeClass*)pNewNode);
		if (Type == nt_custom)	((CNodeCustom*)pNewNode)->memsize = Selected[i].object->GetMemorySize();
		if (Type == nt_text)	((CNodeText*)pNewNode)->memsize = Selected[i].object->GetMemorySize();
		if (Type == nt_unicode)	((CNodeUnicode*)pNewNode)->memsize = Selected[i].object->GetMemorySize();
		if (Type == nt_vtable)
		{
			for (int i = 0; i < 10; i++)
			{
				CNodeVTable* pVTable = (CNodeVTable*)pNewNode;
				CNodeFunctionPtr* pFun = new CNodeFunctionPtr;
				pFun->offset = i * 8;
				pFun->pParent = pVTable;
				pVTable->Nodes.push_back(pFun);
			}
		}
		if (Type == nt_pointer)
		{
			CNodePtr*	pPtr = (CNodePtr*)pNewNode;
			CNodeClass* pClass = (CNodeClass*)theApp.CreateNewNode(nt_class);
			MakeBasicClass(pClass);
			pPtr->pNode = pClass;
		}
		if (Type == nt_array)
		{
			CNodeArray* pArray = (CNodeArray*)pNewNode;
			CNodeClass* pClass = (CNodeClass*)theApp.CreateNewNode(nt_class);
			MakeBasicClass(pClass);
			pArray->pNode = pClass;
		}
		if (Type == nt_instance)
		{
			CNodeClassInstance* pInstance = (CNodeClassInstance*)pNewNode;
			CNodeClass*			pClass = (CNodeClass*)theApp.CreateNewNode(nt_class);
			MakeBasicClass(pClass);
			pInstance->pNode = pClass;
		}

		ReplaceNode((CNodeClass*)Selected[i].object->pParent, FindNodeIndex(Selected[i].object), pNewNode);
		newSelected.push_back(pNewNode);
	}

	Selected.clear();
	for (UINT i = 0; i < newSelected.size(); i++)
	{
		newSelected[i]->bSelected = true;
		CNodeClass* pClass = (CNodeClass*)newSelected[i]->pParent;

		HotSpot spot;
		spot.Address = pClass->offset + newSelected[i]->offset;
		spot.object = newSelected[i];
		Selected.push_back(spot);
	}

	Invalidate(FALSE);
}
Пример #18
0
OBJECT ClosureExpand(OBJECT x, OBJECT env, BOOLEAN crs_wanted,
OBJECT *crs, OBJECT *res_env)
{ OBJECT link, y, res, prnt_env, par, prnt;
  debug3(DCE, D, "[ ClosureExpand( %s, %s, %s, crs, res_env )",
    EchoObject(x), EchoObject(env), bool(crs_wanted));
  assert( type(x) == CLOSURE, "ClosureExpand given non-CLOSURE!");
  assert( predefined(actual(x)) == FALSE, "ClosureExpand given predefined!" );

  /* add tag to x if needed but not provided;  add cross-reference to crs  */
  if( has_tag(actual(x)) )  CrossAddTag(x);
  if( crs_wanted && has_tag(actual(x)) )
  { OBJECT tmp = CopyObject(x, no_fpos);  AttachEnv(env, tmp);
    y = CrossMake(actual(x), tmp, CROSS_TARG);
    New(tmp, CROSS_TARG);  actual(tmp) = y;  Link(tmp, y);
    if( *crs == nilobj )  New(*crs, CR_LIST);   Link(*crs, tmp);
  }

  /* case x is a parameter */
  res = *res_env = nilobj;
  if( is_par(type(actual(x))) )
  { prnt = SearchEnv(env, enclosing(actual(x)));
    if( prnt != nilobj )
    {
      prnt_env = GetEnv(prnt);
      for( link = Down(prnt);  link != prnt;  link = NextDown(link) )
      { Child(par, link);
        if( type(par) == PAR && actual(par) == actual(x) )
        { assert( Down(par) != par, "ExpandCLosure: Down(par)!");
	  Child(res, Down(par));
	  if( dirty(enclosing(actual(par))) || is_enclose(actual(par)) )
	  { debug2(DCE, DD, "copy %s %s", SymName(actual(par)), EchoObject(res));
	    res = CopyObject(res, no_fpos);
	  }
	  else
	  {
	    debug2(DCE, DD, "link %s %s",
	      FullSymName(actual(par), AsciiToFull(".")), EchoObject(res));
	    DeleteLink(Down(par));
	    y = MakeWord(WORD, STR_NOCROSS, &fpos(res));
	    Link(par, y);
	  }
	  ReplaceNode(res, x);
	  if( type(actual(x)) == RPAR && has_body(enclosing(actual(x))) )
	  { debug0(DCR, DDD, "  calling SetEnv from ClosureExpand (a)");
	    *res_env = SetEnv(prnt, nilobj);  DisposeObject(x);
	  }
	  else if( type(actual(x)) == NPAR && imports_encl(actual(x)) )
	  { debug0(DCR, DDD, "  calling SetEnv from ClosureExpand (x)");
	    AttachEnv(env, x);
	    *res_env = SetEnv(x, nilobj);
	  }
	  else
	  { AttachEnv(env, x);
	    debug0(DCR, DDD, "  calling SetEnv from ClosureExpand (b)");
	    *res_env = SetEnv(x, prnt_env);
	  }
	  break;
        }
      }
    }
    else
    {
      /* fail only if there is no default value available */
      if( sym_body(actual(x)) == nilobj )
      {
        debug3(DCE, D, "failing ClosureExpand( %s, crs, %s, %s, res_env )",
	  EchoObject(x), bool(crs_wanted), EchoObject(env));
        Error(9, 2, "no value for parameter %s of symbol %s:", WARN, &fpos(x),
	  SymName(actual(x)), SymName(enclosing(actual(x))));
        Error(9, 1, "symbol with import list misused", FATAL, &fpos(x));
      }
    }
  }

  /* case x is a user-defined symbol or default parameter */
  if( res == nilobj )
  { if( sym_body(actual(x)) == nilobj )
      res = MakeWord(WORD, STR_NOCROSS, &fpos(x));
    else
      res = CopyObject(sym_body(actual(x)), &fpos(x));
    ReplaceNode(res, x);  AttachEnv(env, x);
    debug0(DCR, DDD, "  calling SetEnv from ClosureExpand (c)");
    *res_env = SetEnv(x, nilobj);
  }

  assert( *res_env!=nilobj && type(*res_env)==ENV, "ClosureExpand: *res_env!");
  debug0(DCE, D, "] ClosureExpand returning, res =");
  ifdebug(DCE, D, DebugObject(res));
  debug1(DCE, D, "  environment = %s", EchoObject(*res_env));
  return res;
} /* end ClosureExpand */