OSDN Git Service

2011-09-19 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-coorse.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT LIBRARY COMPONENTS                          --
4 --                                                                          --
5 --           A D A . C O N T A I N E R S . O R D E R E D _ S E T S          --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2004-2011, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17 --                                                                          --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception,   --
20 -- version 3.1, as published by the Free Software Foundation.               --
21 --                                                                          --
22 -- You should have received a copy of the GNU General Public License and    --
23 -- a copy of the GCC Runtime Library Exception along with this program;     --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25 -- <http://www.gnu.org/licenses/>.                                          --
26 --                                                                          --
27 -- This unit was originally developed by Matthew J Heaney.                  --
28 ------------------------------------------------------------------------------
29
30 with Ada.Unchecked_Deallocation;
31
32 with Ada.Containers.Red_Black_Trees.Generic_Operations;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
34
35 with Ada.Containers.Red_Black_Trees.Generic_Keys;
36 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
37
38 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
39 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
40
41 package body Ada.Containers.Ordered_Sets is
42
43    type Iterator is new
44      Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
45         Container : access constant Set;
46         Node      : Node_Access;
47      end record;
48
49    overriding function First (Object : Iterator) return Cursor;
50
51    overriding function Last (Object : Iterator) return Cursor;
52
53    overriding function Next
54      (Object   : Iterator;
55       Position : Cursor) return Cursor;
56
57    overriding function Previous
58      (Object   : Iterator;
59       Position : Cursor) return Cursor;
60
61    ------------------------------
62    -- Access to Fields of Node --
63    ------------------------------
64
65    --  These subprograms provide functional notation for access to fields
66    --  of a node, and procedural notation for modifying these fields.
67
68    function Color (Node : Node_Access) return Color_Type;
69    pragma Inline (Color);
70
71    function Left (Node : Node_Access) return Node_Access;
72    pragma Inline (Left);
73
74    function Parent (Node : Node_Access) return Node_Access;
75    pragma Inline (Parent);
76
77    function Right (Node : Node_Access) return Node_Access;
78    pragma Inline (Right);
79
80    procedure Set_Color (Node : Node_Access; Color : Color_Type);
81    pragma Inline (Set_Color);
82
83    procedure Set_Left (Node : Node_Access; Left : Node_Access);
84    pragma Inline (Set_Left);
85
86    procedure Set_Right (Node : Node_Access; Right : Node_Access);
87    pragma Inline (Set_Right);
88
89    procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
90    pragma Inline (Set_Parent);
91
92    -----------------------
93    -- Local Subprograms --
94    -----------------------
95
96    function Copy_Node (Source : Node_Access) return Node_Access;
97    pragma Inline (Copy_Node);
98
99    procedure Free (X : in out Node_Access);
100
101    procedure Insert_Sans_Hint
102      (Tree     : in out Tree_Type;
103       New_Item : Element_Type;
104       Node     : out Node_Access;
105       Inserted : out Boolean);
106
107    procedure Insert_With_Hint
108      (Dst_Tree : in out Tree_Type;
109       Dst_Hint : Node_Access;
110       Src_Node : Node_Access;
111       Dst_Node : out Node_Access);
112
113    function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
114    pragma Inline (Is_Equal_Node_Node);
115
116    function Is_Greater_Element_Node
117      (Left  : Element_Type;
118       Right : Node_Access) return Boolean;
119    pragma Inline (Is_Greater_Element_Node);
120
121    function Is_Less_Element_Node
122      (Left  : Element_Type;
123       Right : Node_Access) return Boolean;
124    pragma Inline (Is_Less_Element_Node);
125
126    function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
127    pragma Inline (Is_Less_Node_Node);
128
129    procedure Replace_Element
130      (Tree : in out Tree_Type;
131       Node : Node_Access;
132       Item : Element_Type);
133
134    --------------------------
135    -- Local Instantiations --
136    --------------------------
137
138    package Tree_Operations is
139      new Red_Black_Trees.Generic_Operations (Tree_Types);
140
141    procedure Delete_Tree is
142       new Tree_Operations.Generic_Delete_Tree (Free);
143
144    function Copy_Tree is
145       new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
146
147    use Tree_Operations;
148
149    function Is_Equal is
150      new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
151
152    package Element_Keys is
153      new Red_Black_Trees.Generic_Keys
154       (Tree_Operations     => Tree_Operations,
155        Key_Type            => Element_Type,
156        Is_Less_Key_Node    => Is_Less_Element_Node,
157        Is_Greater_Key_Node => Is_Greater_Element_Node);
158
159    package Set_Ops is
160      new Generic_Set_Operations
161       (Tree_Operations  => Tree_Operations,
162        Insert_With_Hint => Insert_With_Hint,
163        Copy_Tree        => Copy_Tree,
164        Delete_Tree      => Delete_Tree,
165        Is_Less          => Is_Less_Node_Node,
166        Free             => Free);
167
168    ---------
169    -- "<" --
170    ---------
171
172    function "<" (Left, Right : Cursor) return Boolean is
173    begin
174       if Left.Node = null then
175          raise Constraint_Error with "Left cursor equals No_Element";
176       end if;
177
178       if Right.Node = null then
179          raise Constraint_Error with "Right cursor equals No_Element";
180       end if;
181
182       pragma Assert (Vet (Left.Container.Tree, Left.Node),
183                      "bad Left cursor in ""<""");
184
185       pragma Assert (Vet (Right.Container.Tree, Right.Node),
186                      "bad Right cursor in ""<""");
187
188       return Left.Node.Element < Right.Node.Element;
189    end "<";
190
191    function "<" (Left : Cursor; Right : Element_Type) return Boolean is
192    begin
193       if Left.Node = null then
194          raise Constraint_Error with "Left cursor equals No_Element";
195       end if;
196
197       pragma Assert (Vet (Left.Container.Tree, Left.Node),
198                      "bad Left cursor in ""<""");
199
200       return Left.Node.Element < Right;
201    end "<";
202
203    function "<" (Left : Element_Type; Right : Cursor) return Boolean is
204    begin
205       if Right.Node = null then
206          raise Constraint_Error with "Right cursor equals No_Element";
207       end if;
208
209       pragma Assert (Vet (Right.Container.Tree, Right.Node),
210                      "bad Right cursor in ""<""");
211
212       return Left < Right.Node.Element;
213    end "<";
214
215    ---------
216    -- "=" --
217    ---------
218
219    function "=" (Left, Right : Set) return Boolean is
220    begin
221       return Is_Equal (Left.Tree, Right.Tree);
222    end "=";
223
224    ---------
225    -- ">" --
226    ---------
227
228    function ">" (Left, Right : Cursor) return Boolean is
229    begin
230       if Left.Node = null then
231          raise Constraint_Error with "Left cursor equals No_Element";
232       end if;
233
234       if Right.Node = null then
235          raise Constraint_Error with "Right cursor equals No_Element";
236       end if;
237
238       pragma Assert (Vet (Left.Container.Tree, Left.Node),
239                      "bad Left cursor in "">""");
240
241       pragma Assert (Vet (Right.Container.Tree, Right.Node),
242                      "bad Right cursor in "">""");
243
244       --  L > R same as R < L
245
246       return Right.Node.Element < Left.Node.Element;
247    end ">";
248
249    function ">" (Left : Element_Type; Right : Cursor) return Boolean is
250    begin
251       if Right.Node = null then
252          raise Constraint_Error with "Right cursor equals No_Element";
253       end if;
254
255       pragma Assert (Vet (Right.Container.Tree, Right.Node),
256                      "bad Right cursor in "">""");
257
258       return Right.Node.Element < Left;
259    end ">";
260
261    function ">" (Left : Cursor; Right : Element_Type) return Boolean is
262    begin
263       if Left.Node = null then
264          raise Constraint_Error with "Left cursor equals No_Element";
265       end if;
266
267       pragma Assert (Vet (Left.Container.Tree, Left.Node),
268                      "bad Left cursor in "">""");
269
270       return Right < Left.Node.Element;
271    end ">";
272
273    ------------
274    -- Adjust --
275    ------------
276
277    procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
278
279    procedure Adjust (Container : in out Set) is
280    begin
281       Adjust (Container.Tree);
282    end Adjust;
283
284    -------------
285    -- Ceiling --
286    -------------
287
288    function Ceiling (Container : Set; Item : Element_Type) return Cursor is
289       Node : constant Node_Access :=
290                Element_Keys.Ceiling (Container.Tree, Item);
291
292    begin
293       if Node = null then
294          return No_Element;
295       end if;
296
297       return Cursor'(Container'Unrestricted_Access, Node);
298    end Ceiling;
299
300    -----------
301    -- Clear --
302    -----------
303
304    procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
305
306    procedure Clear (Container : in out Set) is
307    begin
308       Clear (Container.Tree);
309    end Clear;
310
311    -----------
312    -- Color --
313    -----------
314
315    function Color (Node : Node_Access) return Color_Type is
316    begin
317       return Node.Color;
318    end Color;
319
320    --------------
321    -- Contains --
322    --------------
323
324    function Contains
325      (Container : Set;
326       Item      : Element_Type) return Boolean
327    is
328    begin
329       return Find (Container, Item) /= No_Element;
330    end Contains;
331
332    ---------------
333    -- Copy_Node --
334    ---------------
335
336    function Copy_Node (Source : Node_Access) return Node_Access is
337       Target : constant Node_Access :=
338                  new Node_Type'(Parent  => null,
339                                 Left    => null,
340                                 Right   => null,
341                                 Color   => Source.Color,
342                                 Element => Source.Element);
343    begin
344       return Target;
345    end Copy_Node;
346
347    ------------
348    -- Delete --
349    ------------
350
351    procedure Delete (Container : in out Set; Position : in out Cursor) is
352    begin
353       if Position.Node = null then
354          raise Constraint_Error with "Position cursor equals No_Element";
355       end if;
356
357       if Position.Container /= Container'Unrestricted_Access then
358          raise Program_Error with "Position cursor designates wrong set";
359       end if;
360
361       pragma Assert (Vet (Container.Tree, Position.Node),
362                      "bad cursor in Delete");
363
364       Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
365       Free (Position.Node);
366       Position.Container := null;
367    end Delete;
368
369    procedure Delete (Container : in out Set; Item : Element_Type) is
370       X : Node_Access := Element_Keys.Find (Container.Tree, Item);
371
372    begin
373       if X = null then
374          raise Constraint_Error with "attempt to delete element not in set";
375       end if;
376
377       Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
378       Free (X);
379    end Delete;
380
381    ------------------
382    -- Delete_First --
383    ------------------
384
385    procedure Delete_First (Container : in out Set) is
386       Tree : Tree_Type renames Container.Tree;
387       X    : Node_Access := Tree.First;
388
389    begin
390       if X /= null then
391          Tree_Operations.Delete_Node_Sans_Free (Tree, X);
392          Free (X);
393       end if;
394    end Delete_First;
395
396    -----------------
397    -- Delete_Last --
398    -----------------
399
400    procedure Delete_Last (Container : in out Set) is
401       Tree : Tree_Type renames Container.Tree;
402       X    : Node_Access := Tree.Last;
403
404    begin
405       if X /= null then
406          Tree_Operations.Delete_Node_Sans_Free (Tree, X);
407          Free (X);
408       end if;
409    end Delete_Last;
410
411    ----------------
412    -- Difference --
413    ----------------
414
415    procedure Difference (Target : in out Set; Source : Set) is
416    begin
417       Set_Ops.Difference (Target.Tree, Source.Tree);
418    end Difference;
419
420    function Difference (Left, Right : Set) return Set is
421       Tree : constant Tree_Type :=
422                Set_Ops.Difference (Left.Tree, Right.Tree);
423    begin
424       return Set'(Controlled with Tree);
425    end Difference;
426
427    -------------
428    -- Element --
429    -------------
430
431    function Element (Position : Cursor) return Element_Type is
432    begin
433       if Position.Node = null then
434          raise Constraint_Error with "Position cursor equals No_Element";
435       end if;
436
437       pragma Assert (Vet (Position.Container.Tree, Position.Node),
438                      "bad cursor in Element");
439
440       return Position.Node.Element;
441    end Element;
442
443    -------------------------
444    -- Equivalent_Elements --
445    -------------------------
446
447    function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
448    begin
449       if Left < Right
450         or else Right < Left
451       then
452          return False;
453       else
454          return True;
455       end if;
456    end Equivalent_Elements;
457
458    ---------------------
459    -- Equivalent_Sets --
460    ---------------------
461
462    function Equivalent_Sets (Left, Right : Set) return Boolean is
463       function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
464       pragma Inline (Is_Equivalent_Node_Node);
465
466       function Is_Equivalent is
467          new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
468
469       -----------------------------
470       -- Is_Equivalent_Node_Node --
471       -----------------------------
472
473       function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
474       begin
475          if L.Element < R.Element then
476             return False;
477          elsif R.Element < L.Element then
478             return False;
479          else
480             return True;
481          end if;
482       end Is_Equivalent_Node_Node;
483
484    --  Start of processing for Equivalent_Sets
485
486    begin
487       return Is_Equivalent (Left.Tree, Right.Tree);
488    end Equivalent_Sets;
489
490    -------------
491    -- Exclude --
492    -------------
493
494    procedure Exclude (Container : in out Set; Item : Element_Type) is
495       X : Node_Access := Element_Keys.Find (Container.Tree, Item);
496
497    begin
498       if X /= null then
499          Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
500          Free (X);
501       end if;
502    end Exclude;
503
504    ----------
505    -- Find --
506    ----------
507
508    function Find (Container : Set; Item : Element_Type) return Cursor is
509       Node : constant Node_Access :=
510                Element_Keys.Find (Container.Tree, Item);
511
512    begin
513       if Node = null then
514          return No_Element;
515       end if;
516
517       return Cursor'(Container'Unrestricted_Access, Node);
518    end Find;
519
520    -----------
521    -- First --
522    -----------
523
524    function First (Container : Set) return Cursor is
525    begin
526       if Container.Tree.First = null then
527          return No_Element;
528       end if;
529
530       return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
531    end First;
532
533    function First (Object : Iterator) return Cursor is
534    begin
535       if Object.Container = null then
536          return No_Element;
537       else
538          return
539            Cursor'(
540              Object.Container.all'Unrestricted_Access,
541              Object.Container.Tree.First);
542       end if;
543    end First;
544
545    -------------------
546    -- First_Element --
547    -------------------
548
549    function First_Element (Container : Set) return Element_Type is
550    begin
551       if Container.Tree.First = null then
552          raise Constraint_Error with "set is empty";
553       end if;
554
555       return Container.Tree.First.Element;
556    end First_Element;
557
558    -----------
559    -- Floor --
560    -----------
561
562    function Floor (Container : Set; Item : Element_Type) return Cursor is
563       Node : constant Node_Access :=
564                Element_Keys.Floor (Container.Tree, Item);
565
566    begin
567       if Node = null then
568          return No_Element;
569       end if;
570
571       return Cursor'(Container'Unrestricted_Access, Node);
572    end Floor;
573
574    ----------
575    -- Free --
576    ----------
577
578    procedure Free (X : in out Node_Access) is
579       procedure Deallocate is
580          new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
581
582    begin
583       if X /= null then
584          X.Parent := X;
585          X.Left := X;
586          X.Right := X;
587
588          Deallocate (X);
589       end if;
590    end Free;
591
592    ------------------
593    -- Generic_Keys --
594    ------------------
595
596    package body Generic_Keys is
597
598       -----------------------
599       -- Local Subprograms --
600       -----------------------
601
602       function Is_Greater_Key_Node
603         (Left  : Key_Type;
604          Right : Node_Access) return Boolean;
605       pragma Inline (Is_Greater_Key_Node);
606
607       function Is_Less_Key_Node
608         (Left  : Key_Type;
609          Right : Node_Access) return Boolean;
610       pragma Inline (Is_Less_Key_Node);
611
612       --------------------------
613       -- Local Instantiations --
614       --------------------------
615
616       package Key_Keys is
617         new Red_Black_Trees.Generic_Keys
618           (Tree_Operations     => Tree_Operations,
619            Key_Type            => Key_Type,
620            Is_Less_Key_Node    => Is_Less_Key_Node,
621            Is_Greater_Key_Node => Is_Greater_Key_Node);
622
623       -------------
624       -- Ceiling --
625       -------------
626
627       function Ceiling (Container : Set; Key : Key_Type) return Cursor is
628          Node : constant Node_Access :=
629                   Key_Keys.Ceiling (Container.Tree, Key);
630
631       begin
632          if Node = null then
633             return No_Element;
634          end if;
635
636          return Cursor'(Container'Unrestricted_Access, Node);
637       end Ceiling;
638
639       --------------
640       -- Contains --
641       --------------
642
643       function Contains (Container : Set; Key : Key_Type) return Boolean is
644       begin
645          return Find (Container, Key) /= No_Element;
646       end Contains;
647
648       ------------
649       -- Delete --
650       ------------
651
652       procedure Delete (Container : in out Set; Key : Key_Type) is
653          X : Node_Access := Key_Keys.Find (Container.Tree, Key);
654
655       begin
656          if X = null then
657             raise Constraint_Error with "attempt to delete key not in set";
658          end if;
659
660          Delete_Node_Sans_Free (Container.Tree, X);
661          Free (X);
662       end Delete;
663
664       -------------
665       -- Element --
666       -------------
667
668       function Element (Container : Set; Key : Key_Type) return Element_Type is
669          Node : constant Node_Access :=
670                   Key_Keys.Find (Container.Tree, Key);
671
672       begin
673          if Node = null then
674             raise Constraint_Error with "key not in set";
675          end if;
676
677          return Node.Element;
678       end Element;
679
680       ---------------------
681       -- Equivalent_Keys --
682       ---------------------
683
684       function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
685       begin
686          if Left < Right
687            or else Right < Left
688          then
689             return False;
690          else
691             return True;
692          end if;
693       end Equivalent_Keys;
694
695       -------------
696       -- Exclude --
697       -------------
698
699       procedure Exclude (Container : in out Set; Key : Key_Type) is
700          X : Node_Access := Key_Keys.Find (Container.Tree, Key);
701
702       begin
703          if X /= null then
704             Delete_Node_Sans_Free (Container.Tree, X);
705             Free (X);
706          end if;
707       end Exclude;
708
709       ----------
710       -- Find --
711       ----------
712
713       function Find (Container : Set; Key : Key_Type) return Cursor is
714          Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
715
716       begin
717          if Node = null then
718             return No_Element;
719          end if;
720
721          return Cursor'(Container'Unrestricted_Access, Node);
722       end Find;
723
724       -----------
725       -- Floor --
726       -----------
727
728       function Floor (Container : Set; Key : Key_Type) return Cursor is
729          Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
730
731       begin
732          if Node = null then
733             return No_Element;
734          end if;
735
736          return Cursor'(Container'Unrestricted_Access, Node);
737       end Floor;
738
739       -------------------------
740       -- Is_Greater_Key_Node --
741       -------------------------
742
743       function Is_Greater_Key_Node
744         (Left  : Key_Type;
745          Right : Node_Access) return Boolean
746       is
747       begin
748          return Key (Right.Element) < Left;
749       end Is_Greater_Key_Node;
750
751       ----------------------
752       -- Is_Less_Key_Node --
753       ----------------------
754
755       function Is_Less_Key_Node
756         (Left  : Key_Type;
757          Right : Node_Access) return Boolean
758       is
759       begin
760          return Left < Key (Right.Element);
761       end Is_Less_Key_Node;
762
763       ---------
764       -- Key --
765       ---------
766
767       function Key (Position : Cursor) return Key_Type is
768       begin
769          if Position.Node = null then
770             raise Constraint_Error with
771               "Position cursor equals No_Element";
772          end if;
773
774          pragma Assert (Vet (Position.Container.Tree, Position.Node),
775                         "bad cursor in Key");
776
777          return Key (Position.Node.Element);
778       end Key;
779
780       -------------
781       -- Replace --
782       -------------
783
784       procedure Replace
785         (Container : in out Set;
786          Key       : Key_Type;
787          New_Item  : Element_Type)
788       is
789          Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
790
791       begin
792          if Node = null then
793             raise Constraint_Error with
794               "attempt to replace key not in set";
795          end if;
796
797          Replace_Element (Container.Tree, Node, New_Item);
798       end Replace;
799
800       -----------------------------------
801       -- Update_Element_Preserving_Key --
802       -----------------------------------
803
804       procedure Update_Element_Preserving_Key
805         (Container : in out Set;
806          Position  : Cursor;
807          Process   : not null access procedure (Element : in out Element_Type))
808       is
809          Tree : Tree_Type renames Container.Tree;
810
811       begin
812          if Position.Node = null then
813             raise Constraint_Error with
814               "Position cursor equals No_Element";
815          end if;
816
817          if Position.Container /= Container'Unrestricted_Access then
818             raise Program_Error with
819               "Position cursor designates wrong set";
820          end if;
821
822          pragma Assert (Vet (Container.Tree, Position.Node),
823                         "bad cursor in Update_Element_Preserving_Key");
824
825          declare
826             E : Element_Type renames Position.Node.Element;
827             K : constant Key_Type := Key (E);
828
829             B : Natural renames Tree.Busy;
830             L : Natural renames Tree.Lock;
831
832          begin
833             B := B + 1;
834             L := L + 1;
835
836             begin
837                Process (E);
838             exception
839                when others =>
840                   L := L - 1;
841                   B := B - 1;
842                   raise;
843             end;
844
845             L := L - 1;
846             B := B - 1;
847
848             if Equivalent_Keys (K, Key (E)) then
849                return;
850             end if;
851          end;
852
853          declare
854             X : Node_Access := Position.Node;
855          begin
856             Tree_Operations.Delete_Node_Sans_Free (Tree, X);
857             Free (X);
858          end;
859
860          raise Program_Error with "key was modified";
861       end Update_Element_Preserving_Key;
862
863    end Generic_Keys;
864
865    -----------------
866    -- Has_Element --
867    -----------------
868
869    function Has_Element (Position : Cursor) return Boolean is
870    begin
871       return Position /= No_Element;
872    end Has_Element;
873
874    -------------
875    -- Include --
876    -------------
877
878    procedure Include (Container : in out Set; New_Item : Element_Type) is
879       Position : Cursor;
880       Inserted : Boolean;
881
882    begin
883       Insert (Container, New_Item, Position, Inserted);
884
885       if not Inserted then
886          if Container.Tree.Lock > 0 then
887             raise Program_Error with
888               "attempt to tamper with elements (set is locked)";
889          end if;
890
891          Position.Node.Element := New_Item;
892       end if;
893    end Include;
894
895    ------------
896    -- Insert --
897    ------------
898
899    procedure Insert
900      (Container : in out Set;
901       New_Item  : Element_Type;
902       Position  : out Cursor;
903       Inserted  : out Boolean)
904    is
905    begin
906       Insert_Sans_Hint
907         (Container.Tree,
908          New_Item,
909          Position.Node,
910          Inserted);
911
912       Position.Container := Container'Unrestricted_Access;
913    end Insert;
914
915    procedure Insert
916      (Container : in out Set;
917       New_Item  : Element_Type)
918    is
919       Position : Cursor;
920       pragma Unreferenced (Position);
921
922       Inserted : Boolean;
923
924    begin
925       Insert (Container, New_Item, Position, Inserted);
926
927       if not Inserted then
928          raise Constraint_Error with
929            "attempt to insert element already in set";
930       end if;
931    end Insert;
932
933    ----------------------
934    -- Insert_Sans_Hint --
935    ----------------------
936
937    procedure Insert_Sans_Hint
938      (Tree     : in out Tree_Type;
939       New_Item : Element_Type;
940       Node     : out Node_Access;
941       Inserted : out Boolean)
942    is
943       function New_Node return Node_Access;
944       pragma Inline (New_Node);
945
946       procedure Insert_Post is
947         new Element_Keys.Generic_Insert_Post (New_Node);
948
949       procedure Conditional_Insert_Sans_Hint is
950         new Element_Keys.Generic_Conditional_Insert (Insert_Post);
951
952       --------------
953       -- New_Node --
954       --------------
955
956       function New_Node return Node_Access is
957       begin
958          return new Node_Type'(Parent  => null,
959                                Left    => null,
960                                Right   => null,
961                                Color   => Red_Black_Trees.Red,
962                                Element => New_Item);
963       end New_Node;
964
965    --  Start of processing for Insert_Sans_Hint
966
967    begin
968       Conditional_Insert_Sans_Hint
969         (Tree,
970          New_Item,
971          Node,
972          Inserted);
973    end Insert_Sans_Hint;
974
975    ----------------------
976    -- Insert_With_Hint --
977    ----------------------
978
979    procedure Insert_With_Hint
980      (Dst_Tree : in out Tree_Type;
981       Dst_Hint : Node_Access;
982       Src_Node : Node_Access;
983       Dst_Node : out Node_Access)
984    is
985       Success : Boolean;
986       pragma Unreferenced (Success);
987
988       function New_Node return Node_Access;
989       pragma Inline (New_Node);
990
991       procedure Insert_Post is
992         new Element_Keys.Generic_Insert_Post (New_Node);
993
994       procedure Insert_Sans_Hint is
995         new Element_Keys.Generic_Conditional_Insert (Insert_Post);
996
997       procedure Local_Insert_With_Hint is
998         new Element_Keys.Generic_Conditional_Insert_With_Hint
999           (Insert_Post,
1000            Insert_Sans_Hint);
1001
1002       --------------
1003       -- New_Node --
1004       --------------
1005
1006       function New_Node return Node_Access is
1007          Node : constant Node_Access :=
1008            new Node_Type'(Parent  => null,
1009                           Left    => null,
1010                           Right   => null,
1011                           Color   => Red,
1012                           Element => Src_Node.Element);
1013       begin
1014          return Node;
1015       end New_Node;
1016
1017    --  Start of processing for Insert_With_Hint
1018
1019    begin
1020       Local_Insert_With_Hint
1021         (Dst_Tree,
1022          Dst_Hint,
1023          Src_Node.Element,
1024          Dst_Node,
1025          Success);
1026    end Insert_With_Hint;
1027
1028    ------------------
1029    -- Intersection --
1030    ------------------
1031
1032    procedure Intersection (Target : in out Set; Source : Set) is
1033    begin
1034       Set_Ops.Intersection (Target.Tree, Source.Tree);
1035    end Intersection;
1036
1037    function Intersection (Left, Right : Set) return Set is
1038       Tree : constant Tree_Type :=
1039                Set_Ops.Intersection (Left.Tree, Right.Tree);
1040    begin
1041       return Set'(Controlled with Tree);
1042    end Intersection;
1043
1044    --------------
1045    -- Is_Empty --
1046    --------------
1047
1048    function Is_Empty (Container : Set) return Boolean is
1049    begin
1050       return Container.Tree.Length = 0;
1051    end Is_Empty;
1052
1053    ------------------------
1054    -- Is_Equal_Node_Node --
1055    ------------------------
1056
1057    function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1058    begin
1059       return L.Element = R.Element;
1060    end Is_Equal_Node_Node;
1061
1062    -----------------------------
1063    -- Is_Greater_Element_Node --
1064    -----------------------------
1065
1066    function Is_Greater_Element_Node
1067      (Left  : Element_Type;
1068       Right : Node_Access) return Boolean
1069    is
1070    begin
1071       --  Compute e > node same as node < e
1072
1073       return Right.Element < Left;
1074    end Is_Greater_Element_Node;
1075
1076    --------------------------
1077    -- Is_Less_Element_Node --
1078    --------------------------
1079
1080    function Is_Less_Element_Node
1081      (Left  : Element_Type;
1082       Right : Node_Access) return Boolean
1083    is
1084    begin
1085       return Left < Right.Element;
1086    end Is_Less_Element_Node;
1087
1088    -----------------------
1089    -- Is_Less_Node_Node --
1090    -----------------------
1091
1092    function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1093    begin
1094       return L.Element < R.Element;
1095    end Is_Less_Node_Node;
1096
1097    ---------------
1098    -- Is_Subset --
1099    ---------------
1100
1101    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1102    begin
1103       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1104    end Is_Subset;
1105
1106    -------------
1107    -- Iterate --
1108    -------------
1109
1110    procedure Iterate
1111      (Container : Set;
1112       Process   : not null access procedure (Position : Cursor))
1113    is
1114       procedure Process_Node (Node : Node_Access);
1115       pragma Inline (Process_Node);
1116
1117       procedure Local_Iterate is
1118         new Tree_Operations.Generic_Iteration (Process_Node);
1119
1120       ------------------
1121       -- Process_Node --
1122       ------------------
1123
1124       procedure Process_Node (Node : Node_Access) is
1125       begin
1126          Process (Cursor'(Container'Unrestricted_Access, Node));
1127       end Process_Node;
1128
1129       T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1130       B : Natural renames T.Busy;
1131
1132    --  Start of processing for Iterate
1133
1134    begin
1135       B := B + 1;
1136
1137       begin
1138          Local_Iterate (T);
1139       exception
1140          when others =>
1141             B := B - 1;
1142             raise;
1143       end;
1144
1145       B := B - 1;
1146    end Iterate;
1147
1148    function Iterate (Container : Set)
1149      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1150    is
1151    begin
1152       if Container.Length = 0 then
1153          return Iterator'(null, null);
1154       else
1155          return Iterator'(Container'Unchecked_Access, Container.Tree.First);
1156       end if;
1157    end Iterate;
1158
1159    function Iterate (Container : Set; Start : Cursor)
1160      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1161    is
1162       It : constant Iterator := (Container'Unchecked_Access, Start.Node);
1163    begin
1164       return It;
1165    end Iterate;
1166
1167    ----------
1168    -- Last --
1169    ----------
1170
1171    function Last (Container : Set) return Cursor is
1172    begin
1173       if Container.Tree.Last = null then
1174          return No_Element;
1175       else
1176          return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1177       end if;
1178    end Last;
1179
1180    function Last (Object : Iterator) return Cursor is
1181    begin
1182       if Object.Container = null then
1183          return No_Element;
1184       else
1185          return Cursor'(
1186            Object.Container.all'Unrestricted_Access,
1187                         Object.Container.Tree.Last);
1188       end if;
1189    end Last;
1190
1191    ------------------
1192    -- Last_Element --
1193    ------------------
1194
1195    function Last_Element (Container : Set) return Element_Type is
1196    begin
1197       if Container.Tree.Last = null then
1198          raise Constraint_Error with "set is empty";
1199       else
1200          return Container.Tree.Last.Element;
1201       end if;
1202    end Last_Element;
1203
1204    ----------
1205    -- Left --
1206    ----------
1207
1208    function Left (Node : Node_Access) return Node_Access is
1209    begin
1210       return Node.Left;
1211    end Left;
1212
1213    ------------
1214    -- Length --
1215    ------------
1216
1217    function Length (Container : Set) return Count_Type is
1218    begin
1219       return Container.Tree.Length;
1220    end Length;
1221
1222    ----------
1223    -- Move --
1224    ----------
1225
1226    procedure Move is
1227       new Tree_Operations.Generic_Move (Clear);
1228
1229    procedure Move (Target : in out Set; Source : in out Set) is
1230    begin
1231       Move (Target => Target.Tree, Source => Source.Tree);
1232    end Move;
1233
1234    ----------
1235    -- Next --
1236    ----------
1237
1238    function Next (Position : Cursor) return Cursor is
1239    begin
1240       if Position = No_Element then
1241          return No_Element;
1242       end if;
1243
1244       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1245                      "bad cursor in Next");
1246
1247       declare
1248          Node : constant Node_Access :=
1249                   Tree_Operations.Next (Position.Node);
1250
1251       begin
1252          if Node = null then
1253             return No_Element;
1254          end if;
1255
1256          return Cursor'(Position.Container, Node);
1257       end;
1258    end Next;
1259
1260    procedure Next (Position : in out Cursor) is
1261    begin
1262       Position := Next (Position);
1263    end Next;
1264
1265    function Next (Object : Iterator; Position : Cursor) return Cursor is
1266       pragma Unreferenced (Object);
1267    begin
1268       return Next (Position);
1269    end Next;
1270
1271    -------------
1272    -- Overlap --
1273    -------------
1274
1275    function Overlap (Left, Right : Set) return Boolean is
1276    begin
1277       return Set_Ops.Overlap (Left.Tree, Right.Tree);
1278    end Overlap;
1279
1280    ------------
1281    -- Parent --
1282    ------------
1283
1284    function Parent (Node : Node_Access) return Node_Access is
1285    begin
1286       return Node.Parent;
1287    end Parent;
1288
1289    --------------
1290    -- Previous --
1291    --------------
1292
1293    function Previous (Position : Cursor) return Cursor is
1294    begin
1295       if Position = No_Element then
1296          return No_Element;
1297       end if;
1298
1299       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1300                      "bad cursor in Previous");
1301
1302       declare
1303          Node : constant Node_Access :=
1304                   Tree_Operations.Previous (Position.Node);
1305       begin
1306          if Node = null then
1307             return No_Element;
1308          else
1309             return Cursor'(Position.Container, Node);
1310          end if;
1311       end;
1312    end Previous;
1313
1314    procedure Previous (Position : in out Cursor) is
1315    begin
1316       Position := Previous (Position);
1317    end Previous;
1318
1319    function Previous (Object : Iterator; Position : Cursor) return Cursor is
1320       pragma Unreferenced (Object);
1321    begin
1322       return Previous (Position);
1323    end Previous;
1324
1325    -------------------
1326    -- Query_Element --
1327    -------------------
1328
1329    procedure Query_Element
1330      (Position : Cursor;
1331       Process  : not null access procedure (Element : Element_Type))
1332    is
1333    begin
1334       if Position.Node = null then
1335          raise Constraint_Error with "Position cursor equals No_Element";
1336       end if;
1337
1338       pragma Assert (Vet (Position.Container.Tree, Position.Node),
1339                      "bad cursor in Query_Element");
1340
1341       declare
1342          T : Tree_Type renames Position.Container.Tree;
1343
1344          B : Natural renames T.Busy;
1345          L : Natural renames T.Lock;
1346
1347       begin
1348          B := B + 1;
1349          L := L + 1;
1350
1351          begin
1352             Process (Position.Node.Element);
1353          exception
1354             when others =>
1355                L := L - 1;
1356                B := B - 1;
1357                raise;
1358          end;
1359
1360          L := L - 1;
1361          B := B - 1;
1362       end;
1363    end Query_Element;
1364
1365    ----------
1366    -- Read --
1367    ----------
1368
1369    procedure Read
1370      (Stream    : not null access Root_Stream_Type'Class;
1371       Container : out Set)
1372    is
1373       function Read_Node
1374         (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1375       pragma Inline (Read_Node);
1376
1377       procedure Read is
1378          new Tree_Operations.Generic_Read (Clear, Read_Node);
1379
1380       ---------------
1381       -- Read_Node --
1382       ---------------
1383
1384       function Read_Node
1385         (Stream : not null access Root_Stream_Type'Class) return Node_Access
1386       is
1387          Node : Node_Access := new Node_Type;
1388
1389       begin
1390          Element_Type'Read (Stream, Node.Element);
1391          return Node;
1392
1393       exception
1394          when others =>
1395             Free (Node);
1396             raise;
1397       end Read_Node;
1398
1399    --  Start of processing for Read
1400
1401    begin
1402       Read (Stream, Container.Tree);
1403    end Read;
1404
1405    procedure Read
1406      (Stream : not null access Root_Stream_Type'Class;
1407       Item   : out Cursor)
1408    is
1409    begin
1410       raise Program_Error with "attempt to stream set cursor";
1411    end Read;
1412
1413    procedure Read
1414      (Stream : not null access Root_Stream_Type'Class;
1415       Item   : out Reference_Type)
1416    is
1417    begin
1418       raise Program_Error with "attempt to stream reference";
1419    end Read;
1420
1421    procedure Read
1422      (Stream : not null access Root_Stream_Type'Class;
1423       Item   : out Constant_Reference_Type)
1424    is
1425    begin
1426       raise Program_Error with "attempt to stream reference";
1427    end Read;
1428
1429    ---------------
1430    -- Reference --
1431    ---------------
1432
1433    function Constant_Reference (Container : Set; Position : Cursor)
1434    return Constant_Reference_Type
1435    is
1436       pragma Unreferenced (Container);
1437    begin
1438       if Position.Container = null then
1439          raise Constraint_Error with "Position cursor has no element";
1440       end if;
1441
1442       return (Element => Position.Node.Element'Access);
1443    end Constant_Reference;
1444
1445    function Reference (Container : Set; Position : Cursor)
1446    return Reference_Type
1447    is
1448       pragma Unreferenced (Container);
1449    begin
1450       if Position.Container = null then
1451          raise Constraint_Error with "Position cursor has no element";
1452       end if;
1453
1454       return (Element => Position.Node.Element'Access);
1455    end Reference;
1456
1457    -------------
1458    -- Replace --
1459    -------------
1460
1461    procedure Replace (Container : in out Set; New_Item : Element_Type) is
1462       Node : constant Node_Access :=
1463                Element_Keys.Find (Container.Tree, New_Item);
1464
1465    begin
1466       if Node = null then
1467          raise Constraint_Error with
1468            "attempt to replace element not in set";
1469       end if;
1470
1471       if Container.Tree.Lock > 0 then
1472          raise Program_Error with
1473            "attempt to tamper with elements (set is locked)";
1474       end if;
1475
1476       Node.Element := New_Item;
1477    end Replace;
1478
1479    ---------------------
1480    -- Replace_Element --
1481    ---------------------
1482
1483    procedure Replace_Element
1484      (Tree : in out Tree_Type;
1485       Node : Node_Access;
1486       Item : Element_Type)
1487    is
1488       pragma Assert (Node /= null);
1489
1490       function New_Node return Node_Access;
1491       pragma Inline (New_Node);
1492
1493       procedure Local_Insert_Post is
1494          new Element_Keys.Generic_Insert_Post (New_Node);
1495
1496       procedure Local_Insert_Sans_Hint is
1497          new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1498
1499       procedure Local_Insert_With_Hint is
1500          new Element_Keys.Generic_Conditional_Insert_With_Hint
1501         (Local_Insert_Post,
1502          Local_Insert_Sans_Hint);
1503
1504       --------------
1505       -- New_Node --
1506       --------------
1507
1508       function New_Node return Node_Access is
1509       begin
1510          Node.Element := Item;
1511          Node.Color := Red;
1512          Node.Parent := null;
1513          Node.Right := null;
1514          Node.Left := null;
1515
1516          return Node;
1517       end New_Node;
1518
1519       Hint      : Node_Access;
1520       Result    : Node_Access;
1521       Inserted  : Boolean;
1522
1523       --  Start of processing for Replace_Element
1524
1525    begin
1526       if Item < Node.Element
1527         or else Node.Element < Item
1528       then
1529          null;
1530
1531       else
1532          if Tree.Lock > 0 then
1533             raise Program_Error with
1534               "attempt to tamper with elements (set is locked)";
1535          end if;
1536
1537          Node.Element := Item;
1538          return;
1539       end if;
1540
1541       Hint := Element_Keys.Ceiling (Tree, Item);
1542
1543       if Hint = null then
1544          null;
1545
1546       elsif Item < Hint.Element then
1547          if Hint = Node then
1548             if Tree.Lock > 0 then
1549                raise Program_Error with
1550                  "attempt to tamper with elements (set is locked)";
1551             end if;
1552
1553             Node.Element := Item;
1554             return;
1555          end if;
1556
1557       else
1558          pragma Assert (not (Hint.Element < Item));
1559          raise Program_Error with "attempt to replace existing element";
1560       end if;
1561
1562       Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
1563
1564       Local_Insert_With_Hint
1565         (Tree     => Tree,
1566          Position => Hint,
1567          Key      => Item,
1568          Node     => Result,
1569          Inserted => Inserted);
1570
1571       pragma Assert (Inserted);
1572       pragma Assert (Result = Node);
1573    end Replace_Element;
1574
1575    procedure Replace_Element
1576      (Container : in out Set;
1577       Position  : Cursor;
1578       New_Item  : Element_Type)
1579    is
1580    begin
1581       if Position.Node = null then
1582          raise Constraint_Error with
1583            "Position cursor equals No_Element";
1584       end if;
1585
1586       if Position.Container /= Container'Unrestricted_Access then
1587          raise Program_Error with
1588            "Position cursor designates wrong set";
1589       end if;
1590
1591       pragma Assert (Vet (Container.Tree, Position.Node),
1592                      "bad cursor in Replace_Element");
1593
1594       Replace_Element (Container.Tree, Position.Node, New_Item);
1595    end Replace_Element;
1596
1597    ---------------------
1598    -- Reverse_Iterate --
1599    ---------------------
1600
1601    procedure Reverse_Iterate
1602      (Container : Set;
1603       Process   : not null access procedure (Position : Cursor))
1604    is
1605       procedure Process_Node (Node : Node_Access);
1606       pragma Inline (Process_Node);
1607
1608       procedure Local_Reverse_Iterate is
1609          new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1610
1611       ------------------
1612       -- Process_Node --
1613       ------------------
1614
1615       procedure Process_Node (Node : Node_Access) is
1616       begin
1617          Process (Cursor'(Container'Unrestricted_Access, Node));
1618       end Process_Node;
1619
1620       T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1621       B : Natural renames T.Busy;
1622
1623    --  Start of processing for Reverse_Iterate
1624
1625    begin
1626       B := B + 1;
1627
1628       begin
1629          Local_Reverse_Iterate (T);
1630       exception
1631          when others =>
1632             B := B - 1;
1633             raise;
1634       end;
1635
1636       B := B - 1;
1637    end Reverse_Iterate;
1638
1639    -----------
1640    -- Right --
1641    -----------
1642
1643    function Right (Node : Node_Access) return Node_Access is
1644    begin
1645       return Node.Right;
1646    end Right;
1647
1648    ---------------
1649    -- Set_Color --
1650    ---------------
1651
1652    procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1653    begin
1654       Node.Color := Color;
1655    end Set_Color;
1656
1657    --------------
1658    -- Set_Left --
1659    --------------
1660
1661    procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1662    begin
1663       Node.Left := Left;
1664    end Set_Left;
1665
1666    ----------------
1667    -- Set_Parent --
1668    ----------------
1669
1670    procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1671    begin
1672       Node.Parent := Parent;
1673    end Set_Parent;
1674
1675    ---------------
1676    -- Set_Right --
1677    ---------------
1678
1679    procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1680    begin
1681       Node.Right := Right;
1682    end Set_Right;
1683
1684    --------------------------
1685    -- Symmetric_Difference --
1686    --------------------------
1687
1688    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1689    begin
1690       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1691    end Symmetric_Difference;
1692
1693    function Symmetric_Difference (Left, Right : Set) return Set is
1694       Tree : constant Tree_Type :=
1695                Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1696    begin
1697       return Set'(Controlled with Tree);
1698    end Symmetric_Difference;
1699
1700    ------------
1701    -- To_Set --
1702    ------------
1703
1704    function To_Set (New_Item : Element_Type) return Set is
1705       Tree     : Tree_Type;
1706       Node     : Node_Access;
1707       Inserted : Boolean;
1708       pragma Unreferenced (Node, Inserted);
1709    begin
1710       Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1711       return Set'(Controlled with Tree);
1712    end To_Set;
1713
1714    -----------
1715    -- Union --
1716    -----------
1717
1718    procedure Union (Target : in out Set; Source : Set) is
1719    begin
1720       Set_Ops.Union (Target.Tree, Source.Tree);
1721    end Union;
1722
1723    function Union (Left, Right : Set) return Set is
1724       Tree : constant Tree_Type :=
1725                Set_Ops.Union (Left.Tree, Right.Tree);
1726    begin
1727       return Set'(Controlled with Tree);
1728    end Union;
1729
1730    -----------
1731    -- Write --
1732    -----------
1733
1734    procedure Write
1735      (Stream    : not null access Root_Stream_Type'Class;
1736       Container : Set)
1737    is
1738       procedure Write_Node
1739         (Stream : not null access Root_Stream_Type'Class;
1740          Node   : Node_Access);
1741       pragma Inline (Write_Node);
1742
1743       procedure Write is
1744          new Tree_Operations.Generic_Write (Write_Node);
1745
1746       ----------------
1747       -- Write_Node --
1748       ----------------
1749
1750       procedure Write_Node
1751         (Stream : not null access Root_Stream_Type'Class;
1752          Node   : Node_Access)
1753       is
1754       begin
1755          Element_Type'Write (Stream, Node.Element);
1756       end Write_Node;
1757
1758    --  Start of processing for Write
1759
1760    begin
1761       Write (Stream, Container.Tree);
1762    end Write;
1763
1764    procedure Write
1765      (Stream : not null access Root_Stream_Type'Class;
1766       Item   : Cursor)
1767    is
1768    begin
1769       raise Program_Error with "attempt to stream set cursor";
1770    end Write;
1771
1772    procedure Write
1773      (Stream : not null access Root_Stream_Type'Class;
1774       Item   : Reference_Type)
1775    is
1776    begin
1777       raise Program_Error with "attempt to stream reference";
1778    end Write;
1779
1780    procedure Write
1781      (Stream : not null access Root_Stream_Type'Class;
1782       Item   : Constant_Reference_Type)
1783    is
1784    begin
1785       raise Program_Error with "attempt to stream reference";
1786    end Write;
1787
1788 end Ada.Containers.Ordered_Sets;