generic type Container_Type (<>) is limited private; type Cursor_Type (<>) is private; type Element_Type (<>) is private; with function First (Container : Container_Type) return Cursor_Type is <>; with procedure Clear (Container : in out Container_Type) is <>; with procedure Insert (Container : in out Container_Type; Item : Element_Type) is <>; with function Has_Element (Cursor : Cursor_Type) return Boolean is <>; with function Element (Cursor : Cursor_Type) return Element_Type is <>; with procedure Advance (Cursor : in out Cursor_Type) is <>; procedure Generic_Copy6 (Source : Container_Type; Target : in out Container_Type); generic type Container_Type (<>) is limited private; type Cursor_Type (<>) is private; type Element_Type (<>) is private; with procedure Insert (Container : in out Container_Type; Item : Element_Type) is <>; with function Has_Element (Cursor : Cursor_Type) return Boolean is <>; with function Element (Cursor : Cursor_Type) return Element_Type is <>; with procedure Advance (Cursor : in out Cursor_Type) is <>; with procedure Clear (Container : in out Container_Type) is null; procedure Generic_Copy7 (Source : Cursor_Type; Target : in out Container_Type); generic type Container_Type (<>) is limited private; type Cursor_Type (<>) is private; with procedure Insert (Target : in out Container_Type; Source : Cursor_Type) is <>; with function Has_Element (Cursor : Cursor_Type) return Boolean is <>; with procedure Advance (Cursor : in out Cursor_Type) is <>; with procedure Clear (Container : in out Container_Type) is null; procedure Generic_Copy8 (Source : Cursor_Type; Target : in out Container_Type); with Stacks; generic with package Stack_Types is new Stacks (<>); use Stack_Types; procedure Generic_Stack_Copy4 (Source : Stack'Class; Target : in out Stack'Class); generic type Stack_Type (<>) is limited private; type Cursor_Type (<>) is private; type Element_Type (<>) is private; with function Bottom_Cursor (Stack : Stack_Type) return Cursor_Type is <>; with procedure Clear (Stack : in out Stack_Type) is <>; with procedure Push (Stack : in out Stack_Type; Item : Element_Type) is <>; with function Has_Element (Cursor : Cursor_Type) return Boolean is <>; with function Element (Cursor : Cursor_Type) return Element_Type is <>; with procedure Previous (Cursor : in out Cursor_Type) is <>; procedure Generic_Stack_Copy5 (Source : Stack_Type; Target : in out Stack_Type); with Stacks.Bounded_G; package Integer_Stacks.Bounded is new Integer_Stacks.Bounded_G; pragma Pure (Integer_Stacks.Bounded); with Stacks; pragma Elaborate_All (Stacks); package Integer_Stacks is new Stacks (Integer); pragma Pure (Integer_Stacks); with Stacks_Bounded; pragma Elaborate_All (Stacks_Bounded); package Integer_Stacks_Bounded is new Stacks_Bounded (Integer); pragma Pure (Integer_Stacks_Bounded); with Integer_Stacks_Bounded; use Integer_Stacks_Bounded; with Generic_Stack_Copy5; procedure Integer_Stacks_Bounded_Copy5 is new Generic_Stack_Copy5 (Stack, Cursor, Integer); generic package Stacks.Bounded_G is pragma Pure; type Stack (Capacity : Natural) is new Stacks.Stack with private; procedure Push (Container : in out Stack; Item : in Element_Type); function Top (Container : Stack) return Element_Type; procedure Pop (Container : in out Stack); function Length (Container : Stack) return Natural; procedure Clear (Container : in out Stack); procedure Copy (Source : Stack; Target : in out Stacks.Stack'Class); function Top_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class; function Bottom_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class; type Cursor is new Stacks.Cursor with private; private type Element_Array is array (Positive range <>) of Element_Type; function "=" (L, R : Element_Array) return Boolean is abstract; type Stack (Capacity : Natural) is new Stacks.Stack with record Elements : Element_Array (1 .. Capacity); Top_Index : Natural := 0; end record; type Cursor is new Stacks.Cursor with record Container : access constant Stack; Index : Natural := 0; end record; function Has_Element (Position : Cursor) return Boolean; function Element (Position : Cursor) return Element_Type; procedure Next (Position : in out Cursor); procedure Previous (Position : in out Cursor); end Stacks.Bounded_G; generic procedure Stacks.Generic_Copy3 (Source : Stack'Class; Target : in out Stack'Class); private with Ada.Finalization; generic package Stacks.Unbounded_G is pragma Preelaborate; type Stack is new Stacks.Stack with private; procedure Push (Container : in out Stack; Item : in Element_Type); function Top (Container : Stack) return Element_Type; procedure Pop (Container : in out Stack); function Length (Container : Stack) return Natural; procedure Clear (Container : in out Stack); procedure Copy (Source : Stack; Target : in out Stacks.Stack'Class); function Top_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class; function Bottom_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class; private type Element_Array is array (Positive range <>) of Element_Type; function "=" (L, R : Element_Array) return Boolean is abstract; type Element_Array_Access is access Element_Array; type Rep_Type is new Ada.Finalization.Controlled with record Elements : Element_Array_Access; Top_Index : Natural := 0; end record; overriding procedure Adjust (Rep : in out Rep_Type); overriding procedure Finalize (Rep : in out Rep_Type); type Stack is new Stacks.Stack with record Rep : Rep_Type; end record; type Cursor is new Stacks.Cursor with record Container : access constant Stack; Index : Natural := 0; end record; function Has_Element (Position : Cursor) return Boolean; function Element (Position : Cursor) return Element_Type; procedure Next (Position : in out Cursor); procedure Previous (Position : in out Cursor); end Stacks.Unbounded_G; generic type Element_Type is private; with function "=" (L, R : Element_Type) return Boolean is <>; package Stacks is pragma Pure; type Stack is abstract tagged null record; procedure Push (Container : in out Stack; Item : in Element_Type) is abstract; function Top (Container : Stack) return Element_Type is abstract; procedure Pop (Container : in out Stack) is abstract; function Length (Container : Stack) return Natural is abstract; procedure Clear (Container : in out Stack) is abstract; procedure Copy (Source : Stack; Target : in out Stack'Class) is abstract; procedure Copy2 (Source : Stack'Class; Target : in out Stack'Class); type Cursor is abstract tagged null record; function Top_Cursor (Container : not null access constant Stack) return Cursor'Class is abstract; function Bottom_Cursor (Container : not null access constant Stack) return Cursor'Class is abstract; function Has_Element (Position : Cursor) return Boolean is abstract; function Element (Position : Cursor) return Element_Type is abstract; procedure Next (Position : in out Cursor) is abstract; procedure Previous (Position : in out Cursor) is abstract; end Stacks; generic type Element_Type is private; package Stacks_Bounded is pragma Pure; type Stack (Capacity : Natural) is tagged limited private; procedure Push (Container : in out Stack; Item : in Element_Type); function Top (Container : Stack) return Element_Type; procedure Pop (Container : in out Stack); function Length (Container : Stack) return Natural; procedure Clear (Container : in out Stack); type Cursor is private; function Top_Cursor (Container : Stack) return Cursor; function Bottom_Cursor (Container : Stack) return Cursor; function Has_Element (Position : Cursor) return Boolean; function Element (Position : Cursor) return Element_Type; procedure Next (Position : in out Cursor); procedure Previous (Position : in out Cursor); private type Element_Array is array (Positive range <>) of Element_Type; function "=" (L, R : Element_Array) return Boolean is abstract; type Stack (Capacity : Natural) is tagged limited record Elements : Element_Array (1 .. Capacity); Top_Index : Natural := 0; end record; type Cursor is record Container : access constant Stack; Index : Natural := 0; end record; end Stacks_Bounded; with System; use type System.Address; procedure Generic_Copy6 (Source : Container_Type; Target : in out Container_Type) is C : Cursor_Type := First (Source); begin if Source'Address = Target'Address then return; end if; Clear (Target); while Has_Element (C) loop Insert (Target, Element (C)); Advance (C); end loop; end Generic_Copy6; with System; use type System.Address; procedure Generic_Copy7 (Source : Cursor_Type; Target : in out Container_Type) is C : Cursor_Type := Source; begin Clear (Target); while Has_Element (C) loop Insert (Target, Element (C)); Advance (C); end loop; end Generic_Copy7; with System; use type System.Address; procedure Generic_Copy8 (Source : Cursor_Type; Target : in out Container_Type) is C : Cursor_Type := Source; begin Clear (Target); while Has_Element (C) loop Insert (Target, C); Advance (C); end loop; end Generic_Copy8; with System; use type System.Address; procedure Generic_Stack_Copy4 (Source : Stack'Class; Target : in out Stack'Class) is C : Cursor'Class := Bottom_Cursor (Source'Access); begin if Source'Address = Target'Address then return; end if; Target.Clear; while C.Has_Element loop Target.Push (C.Element); C.Previous; end loop; end Generic_Stack_Copy4; with System; use type System.Address; procedure Generic_Stack_Copy5 (Source : Stack_Type; Target : in out Stack_Type) is C : Cursor_Type := Bottom_Cursor (Source); begin if Source'Address = Target'Address then return; end if; Clear (Target); while Has_Element (C) loop Push (Target, Element (C)); Previous (C); end loop; end Generic_Stack_Copy5; with System; use type System.Address; package body Stacks.Bounded_G is procedure Push (Container : in out Stack; Item : in Element_Type) is E : Element_Array renames Container.Elements; I : Natural renames Container.Top_Index; begin E (I + 1) := Item; I := I + 1; end Push; function Top (Container : Stack) return Element_Type is begin return Container.Elements (Container.Top_Index); end; procedure Pop (Container : in out Stack) is I : Natural renames Container.Top_Index; begin I := I - 1; end; function Length (Container : Stack) return Natural is begin return Container.Top_Index; end; procedure Clear (Container : in out Stack) is begin Container.Top_Index := 0; end; procedure Copy (Source : Stack; Target : in out Stacks.Stack'Class) is begin if Target'Address = Source'Address then return; end if; Target.Clear; for I in 1 .. Source.Top_Index loop Target.Push (Source.Elements (I)); end loop; end Copy; function Top_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class is begin if Container.Top_Index = 0 then return Cursor'(null, 0); else return Cursor'(Container, Container.Top_Index); end if; end Top_Cursor; function Bottom_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class is begin if Container.Top_Index = 0 then return Cursor'(null, 0); else return Cursor'(Container, 1); end if; end Bottom_Cursor; function Has_Element (Position : Cursor) return Boolean is begin return Position.Index > 0; end; function Element (Position : Cursor) return Element_Type is S : Stack renames Position.Container.all; I : constant Positive range 1 .. S.Top_Index := Position.Index; begin return S.Elements (I); end; procedure Next (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare S : Stack renames Position.Container.all; begin if I > S.Top_Index then I := S.Top_Index; else I := I - 1; end if; end; if I = 0 then Position.Container := null; end if; end Next; procedure Previous (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare S : Stack renames Position.Container.all; begin if I >= S.Top_Index then I := 0; Position.Container := null; else I := I + 1; end if; end; end Previous; end Stacks.Bounded_G; with System; use type System.Address; procedure Stacks.Generic_Copy3 (Source : Stack'Class; Target : in out Stack'Class) is C : Cursor'Class := Bottom_Cursor (Source'Access); begin if Source'Address = Target'Address then return; end if; Target.Clear; while C.Has_Element loop Target.Push (C.Element); C.Previous; end loop; end Stacks.Generic_Copy3; with Ada.Unchecked_Deallocation; with System; use type System.Address; package body Stacks.Unbounded_G is procedure Free is new Ada.Unchecked_Deallocation (Element_Array, Element_Array_Access); procedure Push (Container : in out Stack; Item : in Element_Type) is R : Rep_Type renames Container.Rep; I : Natural renames R.Top_Index; begin if R.Elements = null then R.Elements := new Element_Array'(1 .. 1 => Item); I := 1; return; end if; if I = R.Elements'Last then declare X : Element_Array_Access := R.Elements; J : constant Positive := 2 * I; E : Element_Array_Access := new Element_Array (1 .. J); begin Copy : begin E (1 .. I) := X.all; exception when others => Free (E); raise; end Copy; R.Elements := E; Free (X); end; end if; R.Elements (I + 1) := Item; I := I + 1; end Push; function Top (Container : Stack) return Element_Type is R : Rep_Type renames Container.Rep; begin return R.Elements (R.Top_Index); end; procedure Pop (Container : in out Stack) is R : Rep_Type renames Container.Rep; I : Natural renames R.Top_Index; begin I := I - 1; end; function Length (Container : Stack) return Natural is begin return Container.Rep.Top_Index; end; procedure Clear (Container : in out Stack) is begin Container.Rep.Top_Index := 0; end; procedure Copy (Source : Stack; Target : in out Stacks.Stack'Class) is S : Rep_Type renames Source.Rep; begin if Target'Address = Source'Address then return; end if; Target.Clear; for I in 1 .. S.Top_Index loop Target.Push (S.Elements (I)); end loop; end Copy; procedure Adjust (Rep : in out Rep_Type) is X : constant Element_Array_Access := Rep.Elements; I : constant Natural := Rep.Top_Index; begin Rep.Elements := null; Rep.Top_Index := 0; if I > 0 then Rep.Elements := new Element_Array'(X (1 .. I)); Rep.Top_Index := I; end if; end Adjust; procedure Finalize (Rep : in out Rep_Type) is X : Element_Array_Access := Rep.Elements; begin Rep.Elements := null; Rep.Top_Index := 0; Free (X); end; function Top_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class is R : Rep_Type renames Container.Rep; begin if R.Top_Index = 0 then return Cursor'(null, 0); else return Cursor'(Container, R.Top_Index); end if; end; function Bottom_Cursor (Container : not null access constant Stack) return Stacks.Cursor'Class is R : Rep_Type renames Container.Rep; begin if R.Top_Index = 0 then return Cursor'(null, 0); else return Cursor'(Container, 1); end if; end; function Has_Element (Position : Cursor) return Boolean is begin return Position.Index > 0; end; function Element (Position : Cursor) return Element_Type is R : Rep_Type renames Position.Container.Rep; I : constant Positive range 1 .. R.Top_Index := Position.Index; begin return R.Elements (I); end; procedure Next (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare R : Rep_Type renames Position.Container.Rep; begin if I > R.Top_Index then I := R.Top_Index; else I := I - 1; end if; end; if I = 0 then Position.Container := null; end if; end Next; procedure Previous (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare R : Rep_Type renames Position.Container.Rep; begin if I >= R.Top_Index then I := 0; Position.Container := null; else I := I + 1; end if; end; end Previous; end Stacks.Unbounded_G; with System; use type System.Address; package body Stacks is procedure Copy2 (Source : Stack'Class; Target : in out Stack'Class) is C : Cursor'Class := Bottom_Cursor (Source'Access); begin if Source'Address = Target'Address then return; end if; Target.Clear; while C.Has_Element loop Target.Push (C.Element); C.Previous; end loop; end Copy2; end Stacks; with System; use type System.Address; package body Stacks_Bounded is procedure Push (Container : in out Stack; Item : in Element_Type) is E : Element_Array renames Container.Elements; I : Natural renames Container.Top_Index; begin E (I + 1) := Item; I := I + 1; end Push; function Top (Container : Stack) return Element_Type is begin return Container.Elements (Container.Top_Index); end; procedure Pop (Container : in out Stack) is I : Natural renames Container.Top_Index; begin I := I - 1; end; function Length (Container : Stack) return Natural is begin return Container.Top_Index; end; procedure Clear (Container : in out Stack) is begin Container.Top_Index := 0; end; function Top_Cursor (Container : Stack) return Cursor is begin if Container.Top_Index = 0 then return (null, 0); else return (Container'Unchecked_Access, Container.Top_Index); end if; end Top_Cursor; function Bottom_Cursor (Container : Stack) return Cursor is begin if Container.Top_Index = 0 then return (null, 0); else return (Container'Unchecked_Access, 1); end if; end Bottom_Cursor; function Has_Element (Position : Cursor) return Boolean is begin return Position.Index > 0; end; function Element (Position : Cursor) return Element_Type is S : Stack renames Position.Container.all; I : constant Positive range 1 .. S.Top_Index := Position.Index; begin return S.Elements (I); end; procedure Next (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare S : Stack renames Position.Container.all; begin if I > S.Top_Index then I := S.Top_Index; else I := I - 1; end if; end; if I = 0 then Position.Container := null; end if; end Next; procedure Previous (Position : in out Cursor) is I : Natural renames Position.Index; begin if I = 0 then return; end if; declare S : Stack renames Position.Container.all; begin if I >= S.Top_Index then I := 0; Position.Container := null; else I := I + 1; end if; end; end Previous; end Stacks_Bounded; with Integer_Stacks_Bounded; use Integer_Stacks_Bounded; with Generic_Stack_Copy5; procedure Test_Copy5 (S : Stack) is procedure Copy5 is new Generic_Stack_Copy5 (Stack, Cursor, Integer); T : Stack (S.Length); begin Copy5 (Source => S, Target => T); end; with Integer_Stacks_Bounded; use Integer_Stacks_Bounded; with Generic_Copy6; procedure Test_Copy6 (S : Stack) is procedure Copy6 is new Generic_Copy6 (Stack, Cursor, Integer, First => Bottom_Cursor, Insert => Push, Advance => Previous); T : Stack (S.Length); begin Copy6 (Source => S, Target => T); end; with Integer_Stacks_Bounded; use Integer_Stacks_Bounded; with Generic_Copy7; procedure Test_Copy7 (S : in out Stack) is type Integer_Array is array (Positive range <>) of Integer; A : Integer_Array (1 .. S.Length); begin Copy_From_Stack_To_Array : declare I : Positive := A'First; procedure Insert (Container : in out Integer_Array; Item : Integer) is begin Container (I) := Item; I := I + 1; end; procedure Copy7 is new Generic_Copy7 (Integer_Array, Cursor, Integer, Advance => Next); begin Copy7 (Source => S.Top_Cursor, Target => A); end Copy_From_Stack_To_Array; Copy_From_Array_To_Stack : declare function Has_Element (I : Natural) return Boolean is begin return I > 0; end; function Element (I : Natural) return Integer is begin return A (I); end; procedure Advance (I : in out Natural) is begin I := I - 1; end; procedure Copy7 is new Generic_Copy7 (Stack, Natural, Integer, Insert => Push, Clear => Clear); begin Copy7 (Source => A'Last, Target => S); end Copy_From_Array_To_Stack; end Test_Copy7; with Integer_Stacks_Bounded; use Integer_Stacks_Bounded; with Generic_Copy8; procedure Test_Copy8 (S : in out Stack) is type Integer_Array is array (Positive range <>) of Integer; A : Integer_Array (1 .. S.Length); begin Copy_From_Stack_To_Array : declare I : Positive := A'First; procedure Insert (Target : in out Integer_Array; Source : Cursor) is begin Target (I) := Element (Source); I := I + 1; end; procedure Copy8 is new Generic_Copy8 (Integer_Array, Cursor, Advance => Next); begin Copy8 (Source => S.Top_Cursor, Target => A); end Copy_From_Stack_To_Array; Copy_From_Array_To_Stack : declare procedure Insert (Target : in out Stack; Source : Natural) is begin Target.Push (Item => A (Source)); end; function Has_Element (I : Natural) return Boolean is begin return I > 0; end; procedure Advance (I : in out Natural) is begin I := I - 1; end; procedure Copy8 is new Generic_Copy8 (Stack, Natural, Clear => Clear); begin Copy8 (Source => A'Last, Target => S); end Copy_From_Array_To_Stack; end Test_Copy8;