CVS difference for ai05s/ai05-0136-1.txt

Differences between 1.6 and version 1.7
Log of other versions for file ai05s/ai05-0136-1.txt

--- ai05s/ai05-0136-1.txt	2009/06/09 05:27:09	1.6
+++ ai05s/ai05-0136-1.txt	2009/07/09 06:20:50	1.7
@@ -1,4 +1,4 @@
-!standard  A.18.18(1)                                09-06-07    AI05-0136-1/04
+!standard  A.18.18(1)                                09-07-08    AI05-0136-1/05
 !class Amendment 09-02-04
 !status work item 09-02-04
 !status received 09-01-27
@@ -44,13 +44,19 @@
 
 !wording
 
+Add the multiway tree to the list of containers defined in A.18(4.j).
+
+
 A.18.xx The Package Containers.Multiway_Trees
 
+[Editor's Note: What should the actual clause numbers be for these containers?
+A natural insertion would require renumbering all of the indefinite containers.]
+
 The language-defined generic package Containers.Multiway_Trees provides private
 types List and Cursor, and a set of operations for each type. A multiway tree
 container is well-suited to represent nested structures.
 
-A multiway tree container object manages a tree of internal nodes, each of which
+A multiway tree container object manages a tree of internal *nodes*, each of which
 contains an element and pointers to the parent, first child, last child, next
 (successor) sibling, and previous (predecessor) sibling internal nodes. A cursor
 designates a particular node within a tree (and by extension the element
@@ -59,11 +65,10 @@
 container.
 
 A *subtree* is a particular node (which *roots the subtree*) and all of its child
-nodes (including all of the children of the child nodes, recursively). A node
-with no parent node is called an *orphan node*. A particular orphan node can be
-designated as the *root node* of the tree. The subtree rooted by the designated
-root node is the *active portion* of the tree; some operations only operate on
-the active portion of the tree.
+nodes (including all of the children of the child nodes, recursively). There is
+a special node, the *root*, which is always present and has no associated element
+value. The root node provides a place to add nodes to an otherwise empty tree and
+represents the bottom of the tree.
 
 A node that has no children is called a *leaf node*. The *ancestors* of a node
 are the parent node, the parent of the parent node, and so on until a node with
@@ -95,6 +100,7 @@
 package Ada.Containers.Multiway_Trees is
    pragma Preelaborate(Multiway_Trees);
    pragma Remote_Types(Multiway_Trees);
+   [Editor's note: Remote_Types to be consistent with AI05-0084-1.]
 
    type Tree is tagged private;
    pragma Preelaborable_Initialization(Tree);
@@ -106,8 +112,6 @@
 
    No_Element : constant Cursor;
 
-   No_Parent : constant Cursor := No_Element;
-
    function Equal_Subtree (Left_Position : Cursor;
                            Right_Position: Cursor) return Boolean;
 
@@ -117,27 +121,19 @@
 
    function Count (Container : Tree) return Count_Type;
 
-   function Overall_Count (Container : Tree) return Count_Type;
-
    function Subtree_Count (Position : Cursor) return Count_Type;
 
    function Depth (Position : Cursor) return Count_Type;
 
    function Is_Root (Position : Cursor) return Boolean;
 
-   function Is_Orphan (Position : Cursor) return Boolean;
-
    function Is_Leaf (Position : Cursor) return Boolean;
 
    function Root (Container : Tree) return Cursor;
 
-   procedure Set_Root (Container : in out Tree;
-                       Position  : in     Cursor);
-
    procedure Clear (Container : in out Tree);
 
-   function Element (Position : Cursor)
-      return Element_Type;
+   function Element (Position : Cursor) return Element_Type;
 
    procedure Replace_Element (Container : in out Tree;
                               Position  : in     Cursor;
@@ -174,10 +170,6 @@
                   Position  : Cursor := No_Element)
       return Cursor;
 
-   function Overall_Find (Container : Tree;
-                          Item      : Element_Type)
-      return Cursor;
-
    function Ancestor_Find (Container : Tree;
                            Item      : Element_Type;
                            Position  : Cursor)
@@ -186,20 +178,13 @@
    function Contains (Container : Tree;
                       Item      : Element_Type) return Boolean;
 
-   function Overall_Contains (Container : Tree;
-                              Item      : Element_Type) return Boolean;
-
    function Has_Element (Position : Cursor) return Boolean;
 
    procedure Iterate
      (Container : in Tree;
       Process   : not null access procedure (Position : in Cursor));
-
-   procedure Overall_Iterate
-     (Container : in Tree;
-      Process   : not null access procedure (Position : in Cursor));
 
-   function Child_Count (Container : Tree; Parent : Cursor) return Count_Type;
+   function Child_Count (Parent : Cursor) return Count_Type;
 
    function Child_Depth (Parent, Child : Cursor) return Count_Type;
 
@@ -232,10 +217,10 @@
                            New_Item  : in     Element_Type;
                            Count     : in     Count_Type := 1);
 
-   procedure Delete_Child_Subtree (Container : in out Tree;
-                                   Parent    : in     Cursor;
-                                   Position  : in out Cursor;
-                                   Count     : in     Count_Type := 1);
+   procedure Delete_Child_Subtrees (Container : in out Tree;
+                                    Parent    : in     Cursor;
+                                    Position  : in out Cursor;
+                                    Count     : in     Count_Type := 1);
 
    procedure Copy_Subtree (Target   : in out Tree;
                            Parent   : in     Cursor;
@@ -245,11 +230,6 @@
    procedure Splice_Subtree (Target   : in out Tree;
                              Parent   : in     Cursor;
                              Before   : in     Cursor;
-                             Source   : in out Tree);
-
-   procedure Splice_Subtree (Target   : in out Tree;
-                             Parent   : in     Cursor;
-                             Before   : in     Cursor;
                              Source   : in out Tree;
                              Position : in out Cursor);
 
@@ -271,15 +251,13 @@
 
    function Parent (Position : Cursor) return Cursor;
 
-   function First_Child (Container : Tree; Parent : Cursor) return Cursor;
+   function First_Child (Parent : Cursor) return Cursor;
 
-   function First_Child_Element (Container : Tree; Parent : Cursor)
-      return Element_Type;
+   function First_Child_Element (Parent : Cursor) return Element_Type;
 
-   function Last_Child (Container : Tree; Parent : Cursor) return Cursor;
+   function Last_Child (Parent : Cursor) return Cursor;
 
-   function Last_Child_Element (Container : Tree; Parent : Cursor)
-      return Element_Type;
+   function Last_Child_Element (Parent : Cursor) return Element_Type;
 
    function Next_Sibling (Position : Cursor) return Cursor;
 
@@ -314,22 +292,23 @@
 The type Tree is used to represent trees. The type List needs finalization (see
 7.6).
 
-Empty_Tree represents the empty Tree object. It contains no nodes (Count
-(Empty_Tree) returns 0). If an object of type Tree is not otherwise initialized,
+Empty_Tree represents the empty Tree object. It contains only the root node (Count
+(Empty_Tree) returns 1). If an object of type Tree is not otherwise initialized,
 it is initialized to the same value as Empty_Tree.
 
 No_Element represents a cursor that designates no element. If an object of type
 Cursor is not otherwise initialized, it is initialized to the same value as
 No_Element.
 
-No_Parent represents a cursor that represents the parent of an orphan element.
-
 The predefined "=" operator for type Cursor returns True if both cursors are
 No_Element, or designate the same element in the same container.
 
 Execution of the default implementation of the Input, Output, Read, or Write
 attribute of type Cursor raises Program_Error.
 
+Tree'Write writes Tree.Count-1 elements to the stream.
+Tree'Read reads Tree.Count-1 elements from the stream.
+
 Some operations of this generic package have access-to-subprogram parameters. To
 ensure such operations are well-defined, they guard against certain actions by
 the designated subprogram. In particular, some operations check for "tampering
@@ -374,9 +353,12 @@
 
       If Left_Position or Right_Position equals No_Element, raises
       Constraint_Error. If the number of child nodes of the element designated
-      by Left_Position is different than the number of child modes of the
+      by Left_Position is different than the number of child nodes of the
       element designated by Right_Position, the function returns False. If
-      comparing the element designated by Left_Position with the element
+      Left_Position designates a root node and Right_Position does not,
+      the function returns False. If Right_Position designates a
+      root node and Left_Position does not, the function returns False.
+      If comparing the element designated by Left_Position with the element
       designated by Right_Position using the generic formal equality operator
       returns False, the function returns False. Otherwise, it calls
       Equal_Subtree on a cursor designating each child element of the element
@@ -386,14 +368,11 @@
       Any exception raised during the evaluation of element equality is
       propagated.
 
-      [Editor's note: I needed this to define "=" on Trees. We don't support
-      comparing No_Element here, as that doesn't represent a "particular node"
-      and doing so would require passing two container parameters as well. If
-      you need want to compare the entire active tree of a container to some
-      other subtree, pass Root.]
+      [Editor's note: I needed this to define "=" on Trees, as a recursive
+      definition is the only one that makes sense.]
 
       AARM Ramification: Left_Position and Right_Position do not need to be from
-      the same container.
+      the same tree.
 
       AARM Implementation Note: This wording describes the canonical semantics.
       However, the order and number of calls on the formal equality function is
@@ -410,49 +389,36 @@
    function "=" (Left, Right : Tree) return Boolean;
 
       If Left and Right denote the same tree object, then the function returns
-      True. If Child_Count (Left, No_Element) does not equal Child_Count (Right,
-      No_Element), then the function returns False. If Left has a designated
-      root element and Right does not, or vice versa, the function returns
-      False. Otherwise, it calls Equal_Subtree with a cursor designating each
-      orphan element of Left and a cursor designating the corresponding orphan
-      element of Right. If any such call returns False, the function returns
-      False; otherwise it returns True. Any exception raised during the
-      evaluation of element equality is propagated.
-
-      AARM Discussion: We test that the number of orphan elements is the same in
-      each container. We also check that either both or neither of the trees has
-      a designated root. Otherwise, we recursively test that all of the orphan
-      subtrees are equivalent. We don't need to explicitly check the contents of
-      the roots, since a designated root (if present) is always the first orphan
-      node.
+      True. Otherwise, it calls Equal_Subtree with a cursor designating the root
+      node of Left and Right; the result is returned. Any exception raised during
+      the evaluation of Equal_Subtree is propagated.
 
       AARM Implementation Note: Similar considerations apply here as apply to
       Equal_Subtrees. The actual number of calls performed is unspecified.
 
    function Count (Container : Tree) return Count_Type;
-
-      If there is no designated root element of Container, Count returns 0;
-      otherwise Count returns the number of elements in the active subtree of
-      Container.
 
-   function Overall_Count (Container : Tree) return Count_Type;
+      Count returns the number of nodes in Container.
 
-      Overall_Count returns the number of elements in the entire tree Container,
-      including orphan elements and their children.
+      AARM Ramification: Since all tree objects have a root node, this can never
+      return a value of 0. Count (Some_Tree) should always equal
+      Subtree_Count (Root (Some_Tree)).
+
+      [Editor's Note: The Count of an empty tree being 1 is a bit weird. Should
+      we skip the root node here and return a count of 0 instead? Note that would
+      be inconsistent with Subtree_Count (and it would be very strange to skip the
+      root node there).]
 
    function Subtree_Count (Position : Cursor) return Count_Type;
 
       If Position is No_Element, Subtree_Count returns 0; otherwise, Subtree_Count
-      returns the number of elements in the subtree that is rooted by Position.
+      returns the number of nodes in the subtree that is rooted by Position.
 
    function Is_Empty (Container : Tree) return Boolean;
 
-      Equivalent to Overall_Count (Container) = 0.
+      Equivalent to Count (Container) = 1.
 
-      AARM Discussion: We use Overall_Count to ensure that all elements are
-      counted; Count (Container) only counts the active subtree. This routine,
-      of course, should be implemented a O(1), while Overall_Count is probably
-      O(N).
+      AARM Ramification: An empty tree contains just the root node.
 
    function Depth (Position : Cursor) return Count_Type;
 
@@ -460,25 +426,18 @@
       the number of ancestor nodes of the element at Position (including the
       element itself).
 
+      AARM Ramification: Depth (Root (Some_Tree)) = 1.
+
       [Editor's note: Matt suggests that we have this function as well as
-      Child_Depth because this is the most common case. We can't usefully
-      default the Parent parameter in Child_Depth because it is first; putting
-      the parameters in the other order would be inconsistent with all other
-      routines (where the parent comes first) and thus would be confusing in
-      positional calls.]
+      Child_Depth because this is the most common case. We can't default the
+      Parent parameter in Child_Depth since the correct value depends on the
+      container. Should we ignore the root node here and return a Depth of 0
+      in the previous case?]
 
    function Is_Root (Position : Cursor) return Boolean;
-
-      Is_Root returns True if the Position designates the element that is
-      designated as the root of the tree; and returns False otherwise.
-
-   function Is_Orphan (Position : Cursor) return Boolean;
-
-      Is_Orphan returns True if Position designates an element that does not
-      have a parent node; and returns False otherwise.
 
-      AARM Ramification: Is_Orphan returns False if passed No_Element, as
-      No_Element does not designate an element.
+      Is_Root returns True if the Position designates the root node of the
+      tree; and returns False otherwise.
 
    function Is_Leaf (Position : Cursor) return Boolean;
 
@@ -490,48 +449,41 @@
 
    function Root (Container : Tree) return Cursor;
 
-      Root returns a cursor that designates the element that is the designated
-      root element of Container; it returns No_Element if there is no designated
-      root element of Container.
-
-   procedure Set_Root (Container : in out Tree;
-                       Position  : in     Cursor);
-
-      If Position equals No_Element, then Container is set to have no designated
-      root element. If Is_Orphan (Position) is False, Constraint_Error is
-      propagated. Otherwise, the element designated by Position is set as the
-      designated root element designated of Container. The newly designated
-      element becomes the first orphan element of Container.
+      Root returns a cursor that designates the root node of Container.
 
-      AARM Ramification: If Root (Container) /= No_Element, then
-      First_Child (Container, No_Parent) = Root (Container).
+      AARM Ramification: There is always a root node, even in an empty container,
+      so this function never returns No_Element.
 
    procedure Clear (Container : in out Tree);
 
       Removes all the elements from Container.
+
+      AARM Ramification: The root node is not removed; all trees have a root node.
+
+   function Element (Position : Cursor) return Element_Type;
 
-   function Element (Position : Cursor)
-      return Element_Type;
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated. Otherwise, Element returns the element designated by Position.
 
-      If Position equals No_Element, then Constraint_Error is propagated.
-      Otherwise, Element returns the element designated by Position.
+      AARM Ramification: The root node does not contain an element, so that value cannot
+      be read or written.
 
    procedure Replace_Element (Container : in out Tree;
                               Position  : in     Cursor;
                               New_Item  : in     Element_Type);
 
-      If Position equals No_Element, then Constraint_Error is propagated; if
-      Position does not designate an element in Container, then Program_Error is
-      propagated. Otherwise Replace_Element assigns the value New_Item to the
-      element designated by Position.
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated; if Position does not designate an element in Container, then
+      Program_Error is propagated. Otherwise Replace_Element assigns the value New_Item
+      to the element designated by Position.
 
    procedure Query_Element
      (Position : in Cursor;
       Process  : not null access procedure (Element : in Element_Type));
 
-      If Position equals No_Element, then Constraint_Error is propagated.
-      Otherwise, Query_Element calls Process.all with the element designated by
-      Position as the argument. Program_Error is propagated if Process.all
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated. Otherwise, Query_Element calls Process.all with the element
+      designated by Position as the argument. Program_Error is propagated if Process.all
       tampers with the elements of Container. Any exception raised by
       Process.all is propagated.
 
@@ -541,11 +493,11 @@
       Process   : not null access procedure
                       (Element : in out Element_Type));
 
-      If Position equals No_Element, then Constraint_Error is propagated; if
-      Position does not designate an element in Container, then Program_Error is
-      propagated. Otherwise Update_Element calls Process.all with the element
-      designated by Position as the argument. Program_Error is propagated if
-      Process.all tampers with the elements of Container. Any exception raised
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated; if Position does not designate an element in Container, then
+      Program_Error is propagated. Otherwise Update_Element calls Process.all with
+      the element designated by Position as the argument. Program_Error is propagated
+      if Process.all tampers with the elements of Container. Any exception raised
       by Process.all is propagated.
 
       If Element_Type is unconstrained and definite, then the actual Element
@@ -554,7 +506,7 @@
    procedure Assign (Target : in out Tree; Source : Tree);
 
       If Target denotes the same object as Source, the operation has no
-      effect. Otherwise, it clears Target, and then each element of Source is
+      effect. Otherwise, it calls Clear (Target), and then each element of Source is
       assigned to a corresponding element in Target.
 
       AARM To Be Honest: The "corresponding element in Target" has a parent
@@ -571,19 +523,19 @@
                    Source : in out Tree);
 
       If Target denotes the same object as Source, then Move has no effect.
-      Otherwise, Move first calls Clear (Target). Then, the nodes in Source are
-      moved to Target (in the same positions). After Move completes,
-      Overall_Count(Target) is the number of nodes originally in Source, and
-      Overall_Count(Source) is 0.
+      Otherwise, Move first calls Clear (Target). Then, the nodes other than the
+      root node in Source are moved to Target (in the same positions). After Move
+      completes, Count(Target) is the number of nodes originally in Source, and
+      Count(Source) is 1.
 
    procedure Delete (Container : in out Tree;
                      Position  : in out Cursor);
 
-      If Position equals No_Element, then Constraint_Error is propagated. If
-      Position does not designate an element in Container, then Program_Error is
-      propagated. If the element designated by position has any child elements,
-      then Constraint_Error is propagated. Otherwise Delete removes (from
-      Container) the element designated by Position. Finally, Position is set to
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated. If Position does not designate an element in Container, then
+      Program_Error is propagated. If the element designated by position has any
+      child elements, then Constraint_Error is propagated. Otherwise Delete removes
+      (from Container) the element designated by Position. Finally, Position is set to
       No_Element.
 
       AARM Ramification: The check on Position checks that the cursor does not
@@ -593,29 +545,49 @@
       invalid, which means that execution is erroneous, and any result is
       allowed (including not raising an exception).
 
+      The root node cannot be deleted.
+      End AARM Ramification.
+
    procedure Delete_Subtree (Container : in out Tree;
                              Position  : in out Cursor);
+
+      If Position equals No_Element or designates the root node, then Constraint_Error
+      is propagated. If Position does not designate an element in Container, then
+      Program_Error is propagated. Otherwise Delete removes (from Container) the subtree
+      designated by Position (that is, the node designated by Position and all of the
+      descendant nodes of that node), and Position is set to No_Element.
+
+      AARM Ramification: The root node cannot be deleted. To delete the entire contents
+      of the tree, call Clear(Container).
+
+      [Editor's note: We could allow Delete_Subtree on the root node instead,
+      leaving the root node behind. But that's pretty weird. I worded that originally
+      as:
+
+        If Position designates the root node of the tree, Delete removes
+        (from Container) the subtrees represented each child node of the root node
+        (the child node along with all of the descendant nodes of that node), and
+        Position is not changed. Otherwise Delete removes (from Container) the subtree
+        designated by Position, and Position is set to No_Element.
 
-      If Position equals No_Element, then Constraint_Error is propagated. If
-      Position does not designate an element in Container, then Program_Error is
-      propagated. Otherwise Delete removes (from Container) the subtree
-      designated by Position - that is, the element designated by Position along
-      with all of the descendant elements of that element. Finally, Position is
-      set to No_Element.
+      but abandoned it as not really meeting the postcondition.]
 
    procedure Swap (Container : in out Tree;
                    I, J      : in     Cursor);
 
-      If either I or J is No_Element, then Constraint_Error is propagated. If
-      either I or J do not designate an element in Container, then Program_Error
-      is propagated. Otherwise, Swap exchanges the values of the elements
-      designated by I and J.
+      If either I or J equals No_Element or designates the root node, then
+      Constraint_Error is propagated. If either I or J do not designate an element in
+      Container, then Program_Error is propagated. Otherwise, Swap exchanges the values
+      of the elements designated by I and J.
 
       AARM Ramification: After a call to Swap, I designates the element value
       previously designated by J, and J designates the element value previously
       designated by I. The elements position do not change; for instance, the
       parent node and the first child node of I are unchanged by the operation.
 
+      The root nodes do not contain element values, so they cannot be swapped
+      End AARM Ramification.
+
       AARM To be honest: The implementation is not required to actually copy the
       elements if it can do the swap some other way. But it is allowed to copy
       the elements if needed.
@@ -625,32 +597,28 @@
                   Position  : Cursor := No_Element)
       return Cursor;
 
-      If Position is not No_Element, and does not designate an element in
-      Container, then Program_Error is propagated. Find searches a subtree of
+      If Position is not No_Element, and does not designate a node in Container,
+      then Program_Error is propagated. Find searches a subtree of
       the elements of Container for an element equal to Item (using the generic
       formal equality operator). The search starts at the element designated by
-      Position, or at the designated root element if Position equals No_Element.
-      The search checks the subtree rooted by Position in a depth-first order.
-      If no equal element is found, then Find returns No_Element. Otherwise, it
-      returns a cursor designating the first equal element encountered.
+      Position, or at the root node if Position equals No_Element. The search
+      checks the subtree rooted by Position (or the root node) in a depth-first
+      order. If no equal element is found, then Find returns No_Element. Otherwise,
+      it returns a cursor designating the first equal element encountered.
 
       AARM Ramification: Find does not check any siblings of the element
-      designated by Position.
+      designated by Position. The root node does not contain an element, and
+      therefore it can never be returned, but it can be explicitly passed to
+      Position.
 
       [Editor's note: This would naturally be called "Find_Subtree", but that is
-      a misleading name, as what this does is Find *in* subtree (not finding a
-      subtree). So we stick with plain "Find".]
-
-   function Overall_Find (Container : Tree;
-                          Item      : Element_Type)
-      return Cursor;
+      a misleading name, as what this does is Find *in* a subtree (not finding a
+      subtree). So we stick with plain "Find".
 
-      Overall_Find searches all of the elements of Container for an element
-      equal to Item (using the generic formal equality operator). The search
-      starts at the first orphan element. The search checks each orphan subtree
-      (including the active subtree, if any) in a depth-first order. If no equal
-      element is found, then Overall_Find returns No_Element. Otherwise, it
-      returns a cursor designating the first equal element encountered.
+      The subtle difference in wording for belonging to the correct container
+      is needed as a cursor designating the root node is allowed here, and it does
+      not "designate an element" (anywhere), but it does "designate a node" in
+      Container.]
 
    function Ancestor_Find (Container : Tree;
                            Item      : Element_Type;
@@ -658,7 +626,7 @@
       return Cursor;
 
       If Position is No_Element, then Constraint_Error is propagated. If
-      Position does not designate an element in Container, then Program_Error is
+      Position does not designate a node in Container, then Program_Error is
       propagated. Otherwise, Ancestor_Find searches for an element equal to Item
       (using the generic formal equality operator). The search starts at the
       element designated by Position, and checks each ancestor proceeding toward
@@ -671,11 +639,6 @@
 
       Equivalent to Find (Container, Item) /= No_Element.
 
-   function Overall_Contains (Container : Tree;
-                              Item      : Element_Type) return Boolean;
-
-      Equivalent to Overall_Find (Container, Item) /= No_Element.
-
    function Has_Element (Position : Cursor) return Boolean;
 
       Returns True if Position designates an element, and returns False
@@ -689,14 +652,18 @@
      (Container : in Tree;
       Process   : not null access procedure (Position : in Cursor));
 
-      Iterate calls Process.all with a cursor that designates each node in the
-      active portion of Container, starting with the designated root node and
-      proceeding in a depth-first order. Program_Error is propagated if
-      Process.all tampers with the cursors of Container. Any exception raised by
-      Process.all is propagated.
-
-      AARM Ramification: If there is no designated root node, Iterate does
-      nothing; Process.all will not be called at all.
+      Iterate calls Process.all with a cursor that designates each element in
+      Container, starting with the root node and proceeding in a depth-first
+      order. Program_Error is propagated if Process.all tampers with the
+      cursors of Container. Any exception raised by Process.all is propagated.
+
+      AARM Ramification: Process is not called with the root node, which does
+      not have an associated element.
+
+      [Editor's note: It is a bit weird to skip the root node, but it seems better
+      that every cursor has an associated element. The alternative that the root
+      node is returned would require most Process implementations to test Is_Root
+      explicitly before doing any element operations.]
 
       AARM Implementation Note: The purpose of the tamper with cursors check is
       to prevent erroneous execution from the Position parameter of Process.all
@@ -710,57 +677,43 @@
       check.
       End AARM Implementation Note.
 
-   procedure Overall_Iterate
-     (Container : in Tree;
-      Process   : not null access procedure (Position : in Cursor));
+   function Child_Count (Parent : Cursor) return Count_Type;
 
-      Iterate calls Process.all with a cursor that designates each node in the
-      Container of Container, starting with the first orphan node and proceeding
-      in a depth-first order, visiting each orphan subtree (including the active
-      subtree, if any) in order. Program_Error is propagated if Process.all
-      tampers with the cursors of Container. Any exception raised by Process.all
-      is propagated.
-
-   function Child_Count (Container : Tree; Parent : Cursor) return Count_Type;
-
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated. If Parent is equal to
-      No_Parent, then Child_Count returns the number of orphan elements in
-      Container (including the designated root element, if any). Otherwise,
-      Child_Count returns the number of child elements of the element designated
+      Child_Count returns the number of child nodes of the node designated
       by Parent.
 
    function Child_Depth (Parent, Child : Cursor) return Count_Type;
 
-      If Child is equal to No_Element, then Constraint_Error is propagated. If
-      Child does not designate and element in Container, then Program_Error is
-      propagated. If Parent is not equal to No_Parent, and does not designate an
-      element in Container, then Program_Error is propagated. If Parent is equal
-      to No_Parent, Child_Depth returns the number of ancestor nodes of Child
-      (including Child itself). Otherwise, Child_Depth returns the number of
-      ancestor nodes of Child (including Child itself), up to but not including
-      Parent; in this case Program_Error is propagated if Parent is not an
+      If Child or Parent is equal to No_Element, then Constraint_Error is
+      propagated. Otherwise, Child_Depth returns the number of ancestor nodes
+      of Child (including Child itself), up to but not including Parent;
+      in this case Program_Error is propagated if Parent is not an 
       ancestor of Child.
 
+      AARM Ramification: Program_Error is propagated if Parent and Child are
+      nodes in different containers.
+
+      Child_Depth (Root (Some_Tree), Child) + 1 = Depth (Child) as the root
+      is not counted.
+      End AARM Ramification.
+
    procedure Insert_Child (Container : in out Tree;
                            Parent    : in     Cursor;
                            Before    : in     Cursor;
                            New_Item  : in     Element_Type;
                            Count     : in     Count_Type := 1);
 
-      If Parent is not equal to No_Parent, and does not designate an element in
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
+      does not designate a node in Container, then Program_Error is propagated.
+      If Before is not equal to No_Element, and does not designate a node in
       Container, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Container, then
-      Program_Error is propagated. If Before is not equal to No_Element, and
-      Container.Parent (Before) is not equal to Parent, then Constraint_Error is
-      raised. If Parent is equal to No_Parent, Insert_Child inserts Count orphan
-      copies of New_Item prior to the (orphan) element designated by Before. If
-      Before equals No_Element, the new elements are inserted after the last
-      orphan node (if any). Otherwise, Insert_Child inserts Count copies of
-      New_Item as children of Parent prior to the element designated by Before.
-      If Before equals No_Element, the new elements are inserted after the last
-      child node of Parent (if any). Any exception raised during allocation of
-      internal storage is propagated, and Container is not modified.
+      No_Element, and Container.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes
+      containing copies of New_Item and inserts them as children of Parent prior
+      to the element designated by Before. If Before equals No_Element, the new
+      nodes are inserted after the last child node of Parent (if any). Any
+      exception raised during allocation of internal storage is propagated,
+      and Container is not modified.
 
    procedure Insert_Child (Container : in out Tree;
                            Parent    : in     Cursor;
@@ -769,20 +722,17 @@
                            Position  :    out Cursor;
                            Count     : in     Count_Type := 1);
 
-      If Parent is not equal to No_Parent, and does not designate an element in
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
+      does not designate a node in Container, then Program_Error is propagated.
+      If Before is not equal to No_Element, and does not designate a node in
       Container, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Container, then
-      Program_Error is propagated. If Before is not equal to No_Element, and
-      Container.Parent (Before) is not equal to Parent, then Constraint_Error is
-      raised. If Parent is equal to No_Parent, Insert_Child inserts Count orphan
-      copies of New_Item prior to the (orphan) element designated by Before. If
-      Before equals No_Element, the new elements are inserted after the last
-      orphan node (if any). Otherwise, Insert_Child inserts Count copies of
-      New_Item as children of Parent prior to the element designated by Before.
-      If Before equals No_Element, the new elements are inserted after the last
-      child node of Parent (if any). Position designated the first
-      newly-inserted element. Any exception raised during allocation of internal
-      storage is propagated, and Container is not modified.
+      No_Element, and Container.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes
+      containing copies of New_Item and inserts them as children of Parent prior
+      to the element designated by Before. If Before equals No_Element, the new
+      nodes are inserted after the last child node of Parent (if any).
+      Position designates the first newly-inserted node. Any exception raised
+      during allocation of internal storage is propagated, and Container is not modified.
 
    procedure Insert_Child (Container : in out Tree;
                            Parent    : in     Cursor;
@@ -790,18 +740,18 @@
                            Position  :    out Cursor;
                            Count     : in     Count_Type := 1);
 
-      If Parent is not equal to No_Parent, and does not designate an element in Container, then
-      Program_Error is propagated. If Before is not equal to No_Element, and does not designate
-      an element in Container, then Program_Error is propagated. If Before is not equal to
-      No_Element, and Container.Parent (Before) is not equal to Parent, then Constraint_Error
-      is raised. If Parent is equal to No_Parent, Insert_Child inserts Count orphan new elements
-      prior to the (orphan) element designated by Before. If Before equals No_Element,
-      the new elements are inserted after the last orphan node (if any). Otherwise, Insert_Child
-      inserts Count new elements as children of Parent prior to the element designated
-      by Before. If Before equals No_Element, the new elements are inserted after the last child
-      node of Parent (if any). The new elements are initialized by default (see 3.3.1). Position
-      designated the first newly-inserted element. Any exception raised during allocation of
-      internal storage is propagated, and Container is not modified.
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
+      does not designate a node in Container, then Program_Error is propagated.
+      If Before is not equal to No_Element, and does not designate a node in
+      Container, then Program_Error is propagated. If Before is not equal to
+      No_Element, and Container.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes
+      and inserts them as children of Parent prior to the element designated by Before.
+      If Before equals No_Element, the new elements are inserted after the last child
+      node of Parent (if any). The elements contained in the new nodes are
+      initialized by default (see 3.3.1). Position designates the first newly-inserted node.
+      Any exception raised during allocation of internal storage is propagated, and
+      Container is not modified.
 
    procedure Prepend_Child (Container : in out Tree;
                             Parent    : in     Cursor;
@@ -818,28 +768,42 @@
 
       Equivalent to Insert_Child (Container, Parent, Last_Child (Container,
       Parent), New_Item, Count).
+
+   procedure Delete_Child_Subtrees (Container : in out Tree;
+                                    Parent    : in     Cursor;
+                                    Position  : in out Cursor;
+                                    Count     : in     Count_Type := 1);
 
-   procedure Delete_Child_Subtree (Container : in out Tree;
-                                   Parent    : in     Cursor;
-                                   Position  : in out Cursor;
-                                   Count     : in     Count_Type := 1);
-
-      If Position equals No_Element, then Constraint_Error is propagated. If
-      Position does not designate an element in Container, then Program_Error is
-      propagated. If Parent is not equal to No_Parent, and does not designate an
-      element in Container, then Program_Error is propagated. If Position is not
-      equal to No_Element, and Container.Parent (Position) is not equal to
-      Parent, then Constraint_Error is raised. Otherwise Delete removes (from
+      If Parent equals No_Element, then Constraint_Error is propagated. If Parent
+      does not designate a node in Container, then Program_Error is propagated.
+      If Position designates the root node, then Constraint_Error is propagated.
+      If Position does not designate an element in Container, then Program_Error
+      is propagated. If Position is not equal to No_Element, and
+      Container.Parent (Position) is not equal to Parent, then Constraint_Error
+      is propagated. If Position is equal to No_Element, Delete removes (from
+      Container) the first Count child elements of Parent and their dependent
+      elements (or all of the child elements of Parent if there are fewer than
+      Count child elements of Parent). Otherwise Delete removes (from
       Container) Count elements and their dependent elements starting at the
       element designated by Position (or all of the elements starting at
       Position if there are fewer than Count elements starting at Position).
       Finally, Position is set to No_Element.
 
-      [Editor's note: The primary difference of this routine is providing of a
-      Count. This allows the deletion of all of the children of a node without
-      having to write a loop with repeated tests. Container.Delete_Child_Subtree
-      (My_Parent, Position => Container.First_Child (My_Parent), Count =>
-      10000); will delete all of the child nodes.
+      [Editor's note: The primary differences of this routine from Delete_Subtree
+      is providing of a Count and a Parent. The provision of a Parent allows
+      Position to to be No_Element to represent the first child of the Parent.
+      The provision of a Count allows the deletion of all of the children of
+      a node without having to write a loop with repeated tests.
+      Container.Delete_Child_Subtree (My_Parent, Position => No_Element, Count =>
+      10000); will delete all of the child nodes. But note that the Position
+      needs to be a variable (No_Element won't work directly). I did consider
+      dropping the Position parameter completely, giving Delete_First_Child_Subtrees.
+      But that seemed so speciallized that it would rarely be used.
+
+      I also considered making Position parameter an "in" parameter with a default
+      of No_Element. That would be more usable, but would be inconsistent with
+      all of the other container deletion routines (which kill off the cursor for
+      the deleted node, if possible).
 
       We don't provide a Delete_Child that only deletes leaf nodes (as we do for
       the entire container), as that would require pretesting the nodes to
@@ -851,19 +815,20 @@
                            Before   : in     Cursor;
                            Source   : in     Cursor);
 
-      If Parent is not equal to No_Parent, and does not designate an element in
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
+      does not designate a node in Target, then Program_Error is propagated.
+      If Before is not equal to No_Element, and does not designate a node in
       Target, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Target, then
-      Program_Error is propagated. If Before is not equal to No_Element, and
-      Target.Parent (Before) is not equal to Parent, then Constraint_Error is
-      raised. If Source is equal to No_Element, then the operation has no
-      effect. Otherwise, the subtree rooted by Source (which can be from any tree;
-      it does not have to be in Target) is copied (a new subtree is created with
-      the same structure as the Source subtree, with each element initialized
+      No_Element, and Target.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. If Source designates a root node,
+      Constraint_Error is propagated. If Source is equal to No_Element,
+      then the operation has no effect. Otherwise, the subtree
+      rooted by Source (which can be from any tree; it does not have to be a
+      subtree of Target) is copied (new nodes are allocated to create a new subtree
+      with the same structure as the Source subtree, with each element initialized
       from the corresponding element of the Source subtree) and and inserted
       into Target immediately prior to Before, or, if Before equals No_Element,
-      after the last child node of Parent (if any) or if Parent is equal to
-      No_Parent, after the last orphan node. The parent of the newly created
+      after the last child node of Parent (if any). The parent of the newly created
       subtree is set to Parent, and the overall count of Target is incremented
       by Subtree_Count (Source).
 
@@ -871,6 +836,11 @@
       is not modified, so we can use the same routine for both copying within
       and between containers.
 
+      AARM Ramification: We do not allow copying a subtree that includes a
+      root node, as that would requiring inserting a node with no value
+      in the middle of the target tree. To copy an entire tree to another
+      tree object, use Copy.
+
       [Editor's note: Normally, we would call the Source parameter "Position";
       and Target would be "Container" but that seems to imply that the same
       container is required for the Source parameter (which it is not).]
@@ -878,88 +848,72 @@
    procedure Splice_Subtree (Target   : in out Tree;
                              Parent   : in     Cursor;
                              Before   : in     Cursor;
-                             Source   : in out Tree);
-
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Target, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Target, then
-      Program_Error is propagated. If Before is not equal to No_Element, and
-      Target.Parent (Before) is not equal to Parent, then Constraint_Error is
-      raised. Otherwise, if Source denotes the same object as Target, or if
-      there is no active subtree in Source, the operation has no effect.
-      Otherwise, Splice_Subtree reorders elements such that the active subtree
-      is removed from Source and moved to Target. The subtree is inserted as a
-      child of Parent (or, if Parent is equal to No_Parent, as an orphan
-      subtree) prior to the element designated by Before. If Before equals
-      No_Element, the subtree is inserted after the last child node of Parent
-      (if any), or if Parent is equal to No_Parent, after the last orphan node
-      (if any). The overall count of Target is incremented by Count (Source),
-      and Source is set to have no designated root element.
-
-      AARM Ramification: If Source contains non-root orphan nodes, Overall_Count
-      (Source) may not be zero after this operation, as they are not moved.
-      However, the sum of the overall counts for the source and target before
-      Splice_Subtree will be the same as the sum of the overall counts
-      afterwards.
-
-      [Editor's note: This would naturally be called "Splice_Child", but that
-      name is misleading. I originally used just "Splice", but Matt suggested
-      that "Splice_Subtree" is more evokative of what it does.]
-
-   procedure Splice_Subtree (Target   : in out Tree;
-                             Parent   : in     Cursor;
-                             Before   : in     Cursor;
                              Source   : in out Tree;
                              Position : in out Cursor);
 
-      If Position is equal to No_Element then Constraint_Error is propagated. If
-      Parent is not equal to No_Parent, and does not designate an element in
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
+      does not designate a node in Target, then Program_Error is propagated.
+      If Before is not equal to No_Element, and does not designate a node in
       Target, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Target, then
-      Program_Error is propagated. If Position does not equal No_Element, and
-      does not designate a node in Source, then Program_Error is propagated. If
-      Before is not equal to No_Element, and Target.Parent (Before) is not equal
-      to Parent, then Constraint_Error is raised. If Source denotes the same
-      object as Target, then there is no effect if Position equals Before, else
+      No_Element, and Target.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. If Position equals No_Element or designates
+      a root node, Constraint_Error is propagated. If Position does not designate
+      a node in Source, then Program_Error is propagated. If Source denotes the same
+      object as Target, then there is no effect; if Position designates an ancestor
+      of Parent or is equal to Parent, Constraint_Error is propagated; else
       the subtree rooted by the element designated by Position is moved
       immediately prior to Before, or, if Before equals No_Element, after the
-      last child node of Parent (if any) or if Parent is equal to No_Parent,
-      after the last orphan node. In each of these cases, Position and the
-      overall count of Target are unchanged, and the parent of the element
-      designated by Position is set to Parent.
+      last child node of Parent (if any). In each of these cases, Position and the
+      count of Target are unchanged, and the parent of the element designated
+      by Position is set to Parent.
+
+      AARM Reason: We can't allow moving the subtree of Position to a
+      descendant node of the subtree, as the descendant node will be part of the
+      subtree being moved. Thus we have to check Position against Parent.
 
       Otherwise, the subtree designated by Position is removed from Source and
-      moved to Target. The subtree is inserted as a child of Parent (or, if
-      Parent is equal to No_Parent, as an orphan subtree) prior to the element
-      designated by Before. If Before equals No_Element, the subtree is inserted
-      after the last child node of Parent (if any), or if Parent is equal to
-      No_Parent, after the last orphan node (if any). In each of these cases,
-      the overall count of Target is incremented by Subtree_Count (Position),
-      and overall count of Source is decremented by Subtree_Count (Position),
-      Position is updated to represent an element in Target.
+      moved to Target. The subtree is inserted as a child of Parent prior to the
+      element designated by Before. If Before equals No_Element, the subtree is
+      inserted after the last child node of Parent (if any). In each of these cases,
+      the count of Target is incremented by Subtree_Count (Position), and the
+      count of Source is decremented by Subtree_Count (Position), Position is
+      updated to represent an element in Target.
 
       AARM Ramification: If Source is the same as Target, and Position = Before,
       or Next_Sibling(Position) = Before, Splice has no effect, as the subtree
       does not have to move to meet the postcondition.
 
+      We do not allow splicing a subtree that includes a root node, as that
+      would requiring inserting a node with no value in the middle of the
+      target tree. Splice the children of the root node instead.
+
+      For this reason there is no operation to splice an entire tree, as that would
+      necessarily involve splicing a root node.
+      End Ramification.
+
    procedure Splice_Subtree (Container: in out Tree;
                              Parent   : in     Cursor;
                              Before   : in     Cursor;
                              Position : in     Cursor);
 
-      If Position is equal to No_Element then Constraint_Error is propagated. If
-      Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated. If Before is not equal to
-      No_Element, and does not designate an element in Container, then
-      Program_Error is propagated. If Position does not equal No_Element, and
+      If Parent equals No_Element, the Constraint_Error is propagated. If Parent
       does not designate a node in Container, then Program_Error is propagated.
-      If Before is not equal to No_Element, and Container.Parent (Before) is not
-      equal to Parent, then Constraint_Error is raised. If Position equals
-      Before there is no effect. Otherwise, the subtree rooted by the element
-      designated by Position is moved immediately prior to Before, or, if Before
-      equals No_Element, after the last child node of Parent (if any) or if
-      Parent is equal to No_Parent, after the last orphan node. The parent of
-      the element designated by Position is set to Parent.
+      If Before is not equal to No_Element, and does not designate a node in
+      Container, then Program_Error is propagated. If Before is not equal to
+      No_Element, and Target.Parent (Before) is not equal to Parent, then
+      Constraint_Error is propagated. If Position equals No_Element or designates
+      a root node, Constraint_Error is propagated. If Position does not designate
+      a node in Container, then Program_Error is propagated. If Position equals
+      Before, there is no effect. If Position designates an ancestor of Parent
+      or is equal to Parent, Constraint_Error is propagated. Otherwise, the subtree
+      rooted by the element designated by Position is moved immediately prior to
+      Before, or, if Before equals No_Element, after the last child node of Parent
+      (if any). The parent of the element designated by Position is set to Parent.
+
+      AARM Reason: We can't allow moving the subtree of Position to a
+      descendant node of the subtree, as the descendant node will be part of the
+      subtree being moved.
+
 
    procedure Splice_Children (Target          : in out Tree;
                               Target_Parent   : in     Cursor;
@@ -967,38 +921,35 @@
                               Source          : in out Tree;
                               Source_Parent   : in     Cursor);
 
-      If Target_Parent is not equal to No_Parent, and does not designate an
-      element in Target, then Program_Error is propagated. If Before is not
-      equal to No_Element, and does not designate an element in Target, then
-      Program_Error is propagated. If Source_Parent is not equal to No_Parent,
-      and does not designate an element in Source, then Program_Error is
-      propagated. If Before is not equal to No_Element, and Target.Parent
-      (Before) is not equal to Target_Parent, then Constraint_Error is raised.
+      If Target_Parent equals No_Element, then Constraint_Error is propagated.
+      If Target_Parent does not designate a node in Target, then Program_Error
+      is propagated. If Before is not equal to No_Element, and does not designate
+      an element in Target, then Program_Error is propagated. If Source_Parent
+      equals No_Element, Constraint_Error is raised. If Source_Parent does not
+      designate a node in Source, then Program_Error is propagated. If Before
+      is not equal to No_Element, and Target.Parent (Before) is not equal to
+      Target_Parent, then Constraint_Error is raised.
 
       If Source denotes the same object as Target, then:
         * if Target_Parent equals Source_Parent there is no effect; else
-        * if Source_Parent is equal to No_Parent or Source_Parent is an ancestor
-	  of Target_Parent, then Constraint_Error is propagated; else
+        * if Source_Parent is an ancestor of Target_Parent, then Constraint_Error
+          is propagated; else
         * the child elements (and their descendants) of Source_Parent are moved
 	  to be child elements of Target_Parent immediately prior to Before, or,
 	  if Before equals No_Element, after the last child node of
-	  Target_Parent (if any) or if Target_Parent is equal to No_Parent,
-	  after the last orphan node. The parent of each moved child element is
+	  Target_Parent (if any). The parent of each moved child element is
 	  set to Target_Parent.
 
-      AARM Reason: We can't allow moving the children of Source_Parent to an
+      AARM Reason: We can't allow moving the children of Source_Parent to a
       descendant node, as the descendant node will be part of one of the
       subtrees being moved.
 
       Otherwise (if Source does not denote the same object as Target), the child
       elements (and their descendants) of Source_Parent are removed from Source
-      and moved to Target. If Source_Parent is equal to No_Parent, all of the
-      orphan elements of Source are moved. The child (or orphan) elements are
-      inserted as children of Target_Parent (or, if Target_Parent is equal to
-      No_Parent, as an orphan subtree) prior to the element designated by
-      Before. If Before equals No_Element, the child (or orphan) elements are
-      inserted after the last child node of Target_Parent (if any), or if Parent
-      is equal to No_Parent, after the last orphan node (if any). In each of
+      and moved to Target. The child elements are
+      inserted as children of Target_Parent prior to the element designated by
+      Before. If Before equals No_Element, the child elements are
+      inserted after the last child node of Target_Parent (if any). In each of
       these cases, the overall count of Target is incremented by Subtree_Count
       (Source_Parent)-1, and overall count of Source is decremented by
       Subtree_Count (Source_Parent)-1.
@@ -1006,8 +957,8 @@
       AARM Ramification: The node designated by Source_Parent is not moved, thus
       we never need to update Source_Parent.
 
-      Move (Target, Source) could be written Splice_Children (Target, No_Parent,
-      No_Element, Source, No_Parent);
+      Move (Target, Source) could be written Splice_Children (Target, Target.Root,
+      No_Element, Source, Source.Root);
       End AARM Ramification.
 
    procedure Splice_Children (Container       : in out Tree;
@@ -1015,58 +966,49 @@
                               Before          : in     Cursor;
                               Source_Parent   : in     Cursor);
 
-      If Target_Parent is not equal to No_Parent, and does not designate an
-      element in Container, then Program_Error is propagated. If Before is not
-      equal to No_Element, and does not designate an element in Container, then
-      Program_Error is propagated. If Source_Parent is not equal to No_Parent,
-      and does not designate an element in Container, then Program_Error is
-      propagated. If Before is not equal to No_Element, and Container.Parent
-      (Before) is not equal to Target_Parent, then Constraint_Error is raised.
-      If Target_Parent equals Source_Parent there is no effect. If Source_Parent
-      is equal to No_Parent or Source_Parent is an ancestor of Target_Parent,
-      then Constraint_Error is propagated. Otherwise the child elements (and
-      their descendants) of Source_Parent are moved to be child elements of
-      Target_Parent immediately prior to Before, or, if Before equals
-      No_Element, after the last child node of Target_Parent (if any) or if
-      Target_Parent is equal to No_Parent, after the last orphan node. The
+      If Target_Parent equals No_Element, then Constraint_Error is propagated.
+      If Target_Parent does not designate a node in Container, then Program_Error
+      is propagated. If Before is not equal to No_Element, and does not designate
+      an element in Container, then Program_Error is propagated. If Source_Parent
+      equals No_Element, Constraint_Error is raised. If Source_Parent does not
+      designate a node in Container, then Program_Error is propagated. If Before
+      is not equal to No_Element, and Container.Parent (Before) is not equal to
+      Target_Parent, then Constraint_Error is raised. If Target_Parent equals
+      Source_Parent there is no effect. If Source_Parent is an ancestor of
+      Target_Parent, then Constraint_Error is propagated. Otherwise the child
+      elements (and their descendants) of Source_Parent are moved to be child
+      elements of Target_Parent immediately prior to Before, or, if Before equals
+      No_Element, after the last child node of Target_Parent (if any). The
       parent of each moved child element is set to Target_Parent.
 
    function Parent (Position : Cursor) return Cursor;
 
-      If Position is equal to No_Element then Constraint_Error is propagated. If
-      the element designated by Position is an orphan element, No_Parent is
-      returned. Otherwise, a cursor designating the parent element of the
-      element designated by Position is returned.
-
-   function First_Child (Container : Tree; Parent : Cursor) return Cursor;
-
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated. If Parent is equal to
-      No_Parent, First_Child returns a cursor designating the first orphan
-      element in Container; if there is no such element, No_Element is returned.
+      If Position is equal to No_Element, then Constraint_Error is propagated.
+      If Position designates a root node, No_Element is returned. Otherwise,
+      a cursor designating the parent node of the node designated by Position
+      is returned.
+
+   function First_Child (Parent : Cursor) return Cursor;
+
+      If Parent is equal to No_Element, then Constraint_Error is propagated.
       Otherwise, First_Child returns a cursor designating the first child
-      element of the element designated by Parent; if ther is no such element,
+      node of the node designated by Parent; if there is no such node,
       No_Element is returned.
 
-   function First_Child_Element (Container : Tree; Parent : Cursor)
-      return Element_Type;
+   function First_Child_Element (Parent : Cursor) return Element_Type;
 
-      Equivalent to Element (First_Child (Container, Parent)).
+      Equivalent to Element (First_Child (Parent)).
 
-   function Last_Child (Container : Tree; Parent : Cursor) return Cursor;
+   function Last_Child (Parent : Cursor) return Cursor;
 
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated. If Parent is equal to
-      No_Parent, Last_Child returns a cursor designating the last orphan element
-      in Container; if there is no such element, No_Element is returned.
-      Otherwise, Last_Child returns a cursor designating the last child element
-      of the element designated by Parent; if there is no such element,
-      No_Element is returned.
+      If Parent is equal to No_Element, then Constraint_Error is propagated.
+      Otherwise, Last_Child returns a cursor designating the last child node
+      of the node designated by Parent; if there is no such node, No_Element
+      is returned.
 
-   function Last_Child_Element (Container : Tree; Parent : Cursor)
-      return Element_Type;
+   function Last_Child_Element (Parent : Cursor) return Element_Type;
 
-      Equivalent to Element (Last_Child (Container, Parent)).
+      Equivalent to Element (Last_Child (Parent)).
 
    function Next_Sibling (Position : Cursor) return Cursor;
 
@@ -1095,15 +1037,13 @@
       Parent    : in     Cursor;
       Process   : not null access procedure (Position : in Cursor));
 
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated.
+      If Parent equals No_Element, then Constraint_Error is propagated.
+      If Parent does not designate a node in Container, then Program_Error is
+      propagated.
 
-      If Parent is equal to No_Parent, Iterate_Children calls Process.all with a
-      cursor that designates each orphan node in Container, starting with the
-      first orphan node and moving the cursor as per the Next_Sibling function.
-      Otherwise, Iterate_Children calls Process.all with a cursor that
-      designates each child node of Parent, starting with the first child node
-      and moving the cursor as per the Next_Sibling function.
+      Iterate_Children calls Process.all with a cursor that designates each
+      child node of Parent, starting with the first child node and moving the
+      cursor as per the Next_Sibling function.
 
       Program_Error is propagated if Process.all tampers with the cursors of
       Container. Any exception raised by Process.all is propagated.
@@ -1113,15 +1053,13 @@
       Parent    : in     Cursor;
       Process   : not null access procedure (Position : in Cursor));
 
-      If Parent is not equal to No_Parent, and does not designate an element in
-      Container, then Program_Error is propagated.
+      If Parent equals No_Element, then Constraint_Error is propagated.
+      If Parent does not designate a node in Container, then Program_Error is
+      propagated.
 
-      If Parent is equal to No_Parent, Iterate_Children calls Process.all with a
-      cursor that designates each orphan node in Container, starting with the
-      last orphan node and moving the cursor as per the Previous_Sibling
-      function. Otherwise, Iterate_Children calls Process.all with a cursor that
-      designates each child node of Parent, starting with the last child node
-      and moving the cursor as per the Previous_Sibling function.
+      Iterate_Children calls Process.all with a cursor that designates each
+      child node of Parent, starting with the last child node and moving the
+      cursor as per the Previous_Sibling function.
 
       Program_Error is propagated if Process.all tampers with the cursors of
       Container. Any exception raised by Process.all is propagated.
@@ -1146,14 +1084,14 @@
 A Cursor value is invalid if any of the following have occurred since it was created:
 * The tree that contains the element it designates has been finalized;
 * The tree that contains the element it designates has been used as the Source or Target of a call to Move;
-* A subtree that contains the element it designated has been moved to a
-  different tree by a call to Splice_Children or Splice_Subtree; or
-* The element it designates has been deleted.
-
-[Editor's note: We have to include moving a subtree to a different container as
-a cause of invalidating a cursor. It appears that the case of a full list splice
-is missing from the list of A.18.3(153-156), as it should invalidate cursors
-that point into the source list.]
+* The tree that contains the element it designates has been used as the Target of a call to Assign
+  or the target of an assignment_statement;
+* The element it designates has been removed from the tree that previously contained the element.
+
+AARM Discussion: We talk about which tree the element was removed from in order to handle
+splicing nodes from one tree to another. The node still exists, but any cursors that designate
+it in the original tree are now invalid. This bullet covers removals caused by calls to Clear,
+Delete, Delete_Subtree, Delete_Child_Subtree, Splice_Children, and Splice_Subtree.
 
 The result of "=" or Has_Element is unspecified if it is called with an invalid
 cursor parameter. Execution is erroneous if any other subprogram declared in
@@ -1173,7 +1111,7 @@
 No storage associated with a multiway tree object shall be lost upon assignment
 or scope exit.
 
-The execution of an assignment_statement for a list shall have the effect of
+The execution of an assignment_statement for a tree shall have the effect of
 copying the elements from the source tree object to the target tree object.
 
 AARM Implementation Note: An assignment of a Tree is a "deep" copy; that is the
@@ -1222,8 +1160,8 @@
 Static Semantics
 
 The declaration of the generic library package
-Containers.Indefinite_Multiway_Trees has the same contents as
-Containers.Multiway_Trees except:
+Containers.Indefinite_Multiway_Trees has the same contents and
+semantics as Containers.Multiway_Trees except:
 
 * The generic formal Element_Type is indefinite.
 * The procedure with the profile:
@@ -1244,10 +1182,77 @@
 
 The actual Element parameter of access subprogram Process of Update_Element may
 be constrained even if Element_Type is unconstrained.
+
+A.18.ZZ The Package Containers.Bounded_Multiway_Trees
+
+
+The language-defined generic package Containers.Bounded_Multiway_Trees
+provides a private type Tree and a set of operations. It provides the same
+operations as the package Containers.Multiway_Trees (see A.18.XX), with the
+difference that the maximum storage is bounded.
+
+Static Semantics
+
+The declaration of the generic library package Containers.Bounded_Multiway_Trees
+has the same contents and semantics as Containers.Multiway_Trees except:
+
+    * pragma Preelaborate is replaced with pragma Pure.
 
-[** TBD** We need to define a bounded form similarly to the ones in AI05-0001-1. Copy the linked list
-to the extent possible.]
+      AARM implementation note: Package
+      Containers.Bounded_Multiway_Trees cannot depend on
+      package Ada.Finalization (because that package has Preelaborate
+      categorization).
 
+    * The type Tree is declared with a discriminant that specifies the
+      capacity (maximum number of elements) as follows:
+
+         type Tree (Capacity : Count_Type) is tagged private;
+
+    * The type Tree needs finalization if and only if type
+      Element_Type needs finalization.
+
+    * The allocation of internal storage includes a check that the
+      capacity is not exceeded, and Capacity_Error is propagated
+      if this check fails.
+
+    * In procedure Assign, if Source length is greater than Target
+      capacity, then Capacity_Error is propagated.
+
+    * Function Copy is declared as follows:
+
+         function Copy (Source : Tree; Capacity : Count_Type := 0)
+	   return List;
+
+      If Capacity is 0, then the tree capacity is the count of
+      Source; if Capacity is equal to or greater than Source.Count,
+      the tree capacity equals the value of the Capacity parameter;
+      otherwise, the operation propagates Capacity_Error.
+
+    * In the five-parameter procedure Splice_Subtree, if Source is
+      not the same object as Target, if the sum of Target.Count and
+      Subtree_Count (Position) is greater than Target.Capacity, then
+      Splice_Subtree propagates Capacity_Error.
+
+    * In the five-parameter procedure Splice_Children, if Source is
+      not the same object as Target, if the sum of if Target.Count
+      and Subtree_Count (Source_Parent)-1 is greater than Target.Capacity,
+      then Splice_Children raises Capacity_Error.
+
+Bounded Errors
+
+It is a bounded error to use a tree if it was the target of an
+assignment_statement whose source was in the middle of an operation
+that disallows tampering with cursors [Redundant: or elements].
+Either Program_Error is raised, or the operation proceeds as defined.
+
+Implementation Advice
+
+Bounded tree objects should be implemented without implicit pointers or
+dynamic allocation.
+
+The implementation advice for procedure Move to minimize copying does not
+apply.
+
 !discussion
 
 The author has found that almost all of his large projects contained a least one
@@ -1263,8 +1268,8 @@
 
 Model:
 
-The model is that every element in the tree has an associated doubly-linked list
-of children. Thus we provide almost all of the operations of the list container,
+The basic model is that every element in the tree has an associated doubly-linked
+list of children. Thus we provide almost all of the operations of the list container,
 each with an added Parent parameter. We did not change the basic names of the
 operations for familiarity. We added "_Child" to each name in order to describe
 clearly what is being accessed. We considered leaving the names the same
@@ -1279,32 +1284,34 @@
 We've added the suffix "_Subtree" to a few operations to make it clear that they
 operate on entire subtrees, as opposed to a single element. While this isn't
 strictly necessary, it should enhance readability of code.
+
+Elements are stored in internal nodes (as in the linked list container).
 
-Elements are stored in internal nodes (as in the linked list container). Nodes
-which do not have parents are called "orphan elements" (or possibly "orphan
-nodes", if we need that terminology in the actual wording. These also form a
-list of elements, and the normal "child" operations can be used on the list of
-orphan elements. One of the orphan elements can be designated the "root" of the
-tree. Some operations operate on the tree that starts at the root, but ignore
-other orphan elements and their children.
-
-Orphan elements allow bottom-up tree creation where subtrees are stashed as
-orphan elements until their parent is created (at which time Slice_Children or
-Slice_Subtree would be used to make it a subtree of the appropriate parent).
-Without this capability, bottom up tree creation would require the creation of
+There is a built-in root node in each container. The root node does not contain
+an element value (in order to avoid complications with uninitialized values
+in the indefinite container forms), and it cannot be deleted. A function Root
+is provided to retrieve a cursor to the root node.
+
+The provision of the root node eliminates many special cases, as it is always the
+case that the parent cursor of an element containing node is a real cursor containing
+an (implicit) reference to the container.
+
+However, the root node cannot participate in any operations that require element values,
+including copying or splicing of subtrees.
+
+The effect is that the root node contains a list of child subtrees which are really
+the interesting trees. Thus the children of the root node can be thought of as
+a forest of trees. This organization allows bottom-up tree creation where subtrees
+are stashed as separate subtrees of the root until their parent is created (at which
+time Slice_Children or Slice_Subtree would be used to make it a subtree of the appropriate
+parent). Without this capability, bottom up tree creation would require the creation of
 many container objects (each with overhead) and potentially would require
 copying of the subtrees and elements from one container to another with each
 step (this is certainly the case for a bounded tree container).
 
-We considered making the tree multirooted rather than designating a particular
-root node. Some reviewers considered this too weird, in addition, designating a
-particular root node allows elements to be in the container without being in the
-primary tree, which can be useful in some circumstances.
-
-Most operations that act on the entire tree container only act on the active
-portion of the tree (that is the subtree rooted by the designated root element);
-those usually have a counter-part that has the prefix "Overall_" that act on the
-entire container including all orphan subtrees.
+We considered using No_Element to represent the root. This however required
+passing the container to a number of operations like First_Child, and also caused
+additional wording complications.
 
 Note that we added the Assign and Copy routines here as proposed in AI05-0001-1.
 If we decide not to do that for the other containers, they should be removed
@@ -1312,13 +1319,8 @@
 
 Similarly, we define a bounded form here; in the unlikely event that we decide
 not to adopt AI05-0001-1, it should be removed here.
-
-For all of the subprograms that take a Parent parameter, if the parameter is
-No_Element, the node is inserted at the root of the tree. This is consistent
-with the meaning of the Before parameter in the Insert routines in the existing
-list containers.
 
-Operations that were dropped are:
+Operations that were dropped from the list container are:
   * Delete_First and Delete_Last: These seem unlikely to occur in the context of
     a tree (as opposed to a sequence like a list), and they're very easy to
     write yourself if necessary. [Editor's Note: Dropping these are all Matt's
@@ -1341,98 +1343,73 @@
     elements. And it also doesn't make any sense on the entire container.
 
 
-Note that we left the Container parameter in routines like First_Child, because
-the Parent parameter can be No_Element to represent no parent (an orphan
-element, including the root), and we need to know in which container to look for
-that orphan element. An alternative design would be to have a separate set of
-routines for accessing orphan elements (including the designated root), but that
-would clutter the package and complicate use (a lot of insertion code would have
-to explicitly check to see if it is inserting at the root: a scourge of
-hand-written code that we don't want to duplicate in the containers!).
-
-
-More on the orphan/root model:
-
-The inclusion of orphan elements also allows an implementation of the XML DOM
-to be built directly using one of these tree containers; the XML DOM also
-includes the capability of inserting elements without including them in
-the main tree (we call it the active tree).
-
-The model as defined means that T.First_Child (No_Parent) [where T is a tree
-container] returns the designated root node (if any). If there is no
-designated root node, it returns the first orphan node. Next_Sibling (T.Root)
-returns a non-root orphan node (if any).
-
-This model is slightly annoying, in that T.Last_Child (No_Parent) is unlikely
-to return the designated root node (unless there are no other orphans in the
-container).
-
-We considered an alternative model where both T.First_Child (No_Parent) and
-T.Last_Child (No_Parent) always returns the designated root node (or No_Element
-if there is no root node). In that model, the root node is not an orphan node,
-and the orphan nodes have their own separate list. For that model, we would
-need additional functions First_Orphan and Last_Orphan to be able to access
-the list of non-root orphans. (The list *has* to exist in order to implement
-operations like "=" and Iterate_All; it would be weird not to provide access
-to it.) We also would require a full set of _Sibling operations, because
-T.First_Child (Parent (Some_Element)) would not always return the child list
-that contains Some_Element. Essentially, any code that could operate on an
-orphan subtree and needed to look at the parent would have to test for the
-possibility that the node is an orphan and handle the case of no parent
-specially. This could be very annoying in programs that do bottom-up tree
-construction.
-
-With either model, (individual) operations directly on elements or that involve
-the relationships between elements do not care whether they are operating on an
-orphan subtree or on
-
-
-With the model we selected, most operations do not care if they are working on
-a node that belongs to the active subtree or to some other node. But many
-operations on the entire container only operate on the active subtree.
-
-
-Some reviewers would prefer a "classic" single-rooted tree. Such a model seems
-cleaner on first reflection, but in practice it does not simplify either the wording
-nor the use of the container. In addition, it makes some operations much more complex.
-We want the tree container to allow operations as naturally as possible, extra
-complications are more likely to cause users to abandon the container.
-
-The main definitional problem is how to define the single root. If we used traditional
-node insertion, then we would have to have rules for an empty tree and in addition
-we would need rules to prevent inserting a second root (this would be necessary for
-at least the various Inserts, Splices, Copy_Subtree). But this somewhat silly, given
-that the first operation on every tree object would have to be to insert the one-and-only
-root.
-
-The only sane alternative would be to have a root node that is always present, but can
-be in an empty state. In this case, inserting any node at the root is always illegal
-(and can easily be prevented by simply not allowing the Parent parameter to ever be
-No_Element). But then, we would have to define the idea of an uninitialized element
-for just this one node, and we would probably want a way to "unset" the value of this
-node. This seems like too much complication.
-
-The usage problem comes about because with a single rooted tree, replacing the root
-is impossible. The effect is that a tree transformation that needs to change the root
-is complicated, and a general purpose transformation usually will have to have a
-special case just to handle the root.
+More on the value-less root model:
 
+Since the top-level subtrees can be thought of as a forest of trees, it would
+be easy to build an implementation of the XML DOM directly using one of these
+tree containers. The XML DOM includes the capability of inserting elements
+without including them in the main tree. Such "orphan" elements could be 
+modeled as children of the root node, with the first child representing
+the main tree.
+
+
+We hope that the valueless root model provides the right balance between the orphan
+model used by the XML DOM and a "classic" single-rooted tree. It appears to keep 
+special cases to a minimum, while not straying too far from the typical terminology of
+trees.
+
+A pure single-roots model seems cleaner on first reflection, but in practice it does
+not simplify either the wording nor the use of the container. In addition, it can make
+some operations much more complex. We want the tree container to allow operations as
+naturally as possible, extra complications are more likely to cause users to abandon
+the container.
+
+If we defined the tree using traditional node insertion, then we would have to have
+rules for an empty tree and in addition we would need rules to prevent inserting a
+second root (this would be necessary for at least the various Inserts, Splices, Copy_Subtree).
+But this somewhat silly, given that the first operation on every tree object would have
+to be to insert the one-and-only root.
+
+The alternative of having a root node that is always present, but has an optional value.
+In this case, inserting any node at the root is always illegal (and can easily be prevented
+by simply not allowing the Parent parameter to ever be No_Element). But then, we would have
+to define the idea of an uninitialized element for just this one node, and we would probably
+want a way to "unset" the value of this node. 
+
+Another alternative is to have the root node always present, and have it be default initialized.
+This would not have as much wording complication, but it would have some annoying effects:
+* A empty tree would contain one valid element (which could be read);
+* The value of this extra node would often need to be ignored (if a forest of subtrees is
+  being used) or replaced - this would add many additional opportunities for errors;
+* The indefinite container form could not use this solution, as there is no default initial
+  value for an indefinite object.
+The only solution for the last problem would be to revert to the previous alternative for
+the indefinite forms, making the various forms annoyingly different.
+
+
+In addition, single rooted trees with values have a serious usage problem. That occurs
+because replacing the root is impossible. The effect is that a tree transformation that
+needs to change the root is complicated, and a general purpose transformation usually will
+have to have a special case just to handle the root.
+
 One obvious example is the bottom-up tree construction noted earlier. In order to do that
 in a single-rooted tree, we would have to either use many tree objects (each with associated
 overhead, and in the case of bounded trees, each Splice_Subtree would have to copy the
 nodes and elements as well), or we would have to use dummy nodes to construct onto which
-have to be ignored in later operations. (They couldn't be deleted, because the only
-way to delete the root node of a single-rooted tree is to delete all of the contents of
-the tree. You might be able to swap them with the real root node, but deleting the dummy
-after that would require relinking all of the child nodes of the real root before the
-dummy could be deleted, a complex operation.) On example problem is that the dummy nodes
-would get in the way if/when trees are combined. For instance, consider the expression
-trees in an Ada compiler. The default expressions of a procedure are likely to be stored
-in the symbol table; if constructed bottom-up (as they would be using a parser generator
-like YACC) they would have to have a dummy node at the top if the tree is single rooted.
-When the default expression is later spliced into a call tree, the dummy node would end
-up in the middle of the call tree. Care would have to be taken with every operation to
-avoid this happening.
+have to be ignored in later operations. (They couldn't be deleted, because the root
+node of a single-rooted tree cannot be deleted. You might be able to swap them with the real
+root node [if that is allowed], but deleting the dummy after that would require relinking all
+of the child nodes of the real root before the dummy could be deleted, a complex operation.)
+One example problem is that the dummy nodes would get in the way if/when trees are combined.
+For instance, consider the expression trees in an Ada compiler. The default expressions of
+a procedure are likely to be stored in the symbol table; if constructed bottom-up (as they
+would be using a parser generator like YACC) they would have to have a dummy node at the top
+if the tree is single rooted. When the default expression is later spliced into a call tree,
+the dummy node would end up in the middle of the call tree. Care would have to be taken with
+every operation to avoid this happening.
+
+When the root node does not have a value, it cannot be spliced or copied into any tree, so
+the problem with excess dummy nodes do not occur. 
 
 Even more annoying would be the complications for doing tree transformations. Consider
 again the expression trees in an Ada compiler. One common transformation is to change
@@ -1451,9 +1428,15 @@
         Replace_Element (Position, New_Item => (Kind => Equals));
     end Change_Not_Equals;
 
-However, this does not work for a single-rooted package if the Position happens to be
-at the root (as it would be for the condition of an if statement that consists of a
-single "/="). That's because inserting a second root is never allowed (else the tree
+Since the current package does not allow the root node to have a value, Position cannot
+designate the root node (it cannot designate a call element, obviously). Thus Insert_Child
+will add a node somewhere in the tree, but it won't try to add a second root. More generally,
+tree transformations only involve nodes with values, so they will not (directly) involve
+the root node.
+
+However, this does not work for a single-rooted package allowing values if the Position
+happens to be at the root (as it would be for the condition of an if statement that consists
+of a single "/="). That's because inserting a second root is never allowed (else the tree
 would not be single rooted!). Thus the initial Insert_Child would fail.
 
 Instead, the code would have to resort to using unnatural operations like Swap and would
@@ -1473,43 +1456,10 @@
 transformation on any function call.) It also ends up with the original cursor pointing
 to a different node than the original code (which might be significant).
  
-Because of all of these reasons, we prefer a tree with the ability to have orphans.
 
 
-Further ideas:
 
-* Should we have a function to get the maximum depth of the tree?
-
-* Matt thought that we should add some additional sibling handling routines.
-  In particular, he suggested Sibling_Count, Iterate_Siblings, and First_Sibling,
-  among others. These would occasionally be convinient, but are easily written
-  using the existing routines:
-  Sibling_Count (Tree, Position) = Child_Count (Tree, Parent(Position))
-  First_Sibling (Tree, Position) = First_Child (Tree, Parent(Position))
-  and so on.
-
-  These could be added by defining them using the above equivalences, if desired.
-
-* Should No_Parent be the same as No_Element? Or should it be a function?
-  The problem with No_Parent being the same as No_Element is that No_Element
-  does not include an indication of the container for which there is no parent.
-  That means that an extra Tree parameter is needed on operations that have to
-  be able to work on the list of orphan nodes: First_Child, Last_Child, Find,
-  Overall_Find, etc. (Any routine with an "in" mode Tree and a Cursor parameter
-  probably belongs in this list.) Even if we didn't have orphan nodes, it is
-  convinent that First_Child(Parent(Any_Element)) equals the node itself if
-  Any_Element has no siblings (which of course includes the root).
-
-  An alternative would be for No_Parent to be a function:
-     function No_Parent (Container : Tree) return Cursor;
-  In that case, those extra Tree parameters can be removed. However, since
-  No_Parent does not represent an element and does not have a value, we would
-  need additional wording to prevent reading/setting the value of No_Parent. We
-  also could not use it as a default parameter (but we aren't doing that currently).
-
-  Note that if we allowed reading and setting of the value of No_Parent, we then
-  would essentially be back to the single root model. We discussed the problems with
-  this model above.
+Further ideas:
 
 * More iterators could be useful. One could imagine wanting to visit the child
   nodes before their parents, as well as a straight breadth-first iteration.
@@ -1613,7 +1563,7 @@
    Sample : HTML_Tree.Tree;
    Header, HTML_Body, Paragraph, Working: HTML_Tree.Cursor;
 
-   HTML_Tree.Insert_Child (Sample, Parent => HTML_Tree.No_Element, Position => Header,
+   HTML_Tree.Insert_Child (Sample, Parent => Sample.Root, Position => Header,
      Before => HTML_Tree.No_Element,
      New_Element => Header_HTML_Element'(Init_Element with null record));
    HTML_Tree.Insert_Child (Sample, Parent => Header, Position => HTML_Body,
@@ -1653,7 +1603,7 @@
          Output_Suffix (Node_Element); -- Dispatches.
       end Output_Node;
    begin
-      Output_Node (HTML_Tree.First (Parent => No_Element));
+      Output_Node (HTML_Tree.First (Parent => Sample.Root));
    end Output_Document;
 
 (2) Windows in a GUI.

Questions? Ask the ACAA Technical Agent