aboutsummaryrefslogtreecommitdiffstats
path: root/src/lists.ads
blob: d06170223e126b253d2597befda98b2702335cdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
--  Lists data type.
--  Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 2 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program.  If not, see <gnu.org/licenses>.
with Types; use Types;

generic
   type El_Type is range <>;
package Lists is
   type List_Type is new Nat32;
   for List_Type'Size use 32;

   Null_List : constant List_Type := 0;
   List_All : constant List_Type := 1;

   subtype List_Valid_Type is List_Type range List_All + 1 .. List_Type'Last;

   -----------
   -- Lists --
   -----------

   -- Iir_Kinds_List
   -- Lists of elements.
   -- index is 0 .. nbr_elements - 1.
   --
   -- Append an element to (the end of) the list.
   --   procedure Append_Element (List: in Iir; Element: Iir);
   --
   -- Get the N th element in list, starting from 0.
   -- Return an access to the element or null_iir, if beyond bounds.
   --   function Get_Nth_Element (List: in Iir; N: Natural) return Iir;
   --
   -- Return the last element of the list, or null_iir.
   --   function Get_Last_Element (List: in Iir) return Iir;
   --
   -- Return the first element of the list, or null_iir.
   --   function Get_First_Element (List: in Iir) return Iir;
   --
   -- Replace an element selected by position.
   --   procedure Replace_Nth_Element (List: in Iir_List; N: Natural; El:Iir);
   --
   -- Add (append) an element only if it was not already present in the list.
   -- Return its position.
   --   procedure Add_Element (List: in Iir; El: Iir; Position: out integer);
   --   procedure Add_Element (List: in Iir_List; El: Iir);
   --
   -- Return the number of elements in the list.
   -- This is also 1 + the position of the last element.
   --   function Get_Nbr_Elements (List: in Iir_List) return Natural;
   --
   -- Set the number of elements in the list.
   -- Can be used only to shrink the list.
   --   procedure Set_Nbr_Elements (List: in Iir_List; N: Natural);

   --  Create a list.
   function Create_List return List_Type;

   --  Destroy a list.
   procedure Destroy_List (List : in out List_Type);

   --  Free all the lists.
   procedure Finalize;

   --  Reset to initial state.
   procedure Initialize;

   --  Append ELEMENT to the list.  It's an O(1) operation.
   procedure Append_Element (List : List_Type; Element : El_Type);

   --  Return the first element of the list.
   function Get_First_Element (List : List_Type) return El_Type;

   --  Append EL if not already in LIST.  It's an O(n) operation.
   procedure Add_Element (List : List_Type; El : El_Type);

   -- Return the number of elements in the list.
   -- This is also 1 + the position of the last element.
   function Get_Nbr_Elements (List: List_Type) return Natural;
   pragma Inline (Get_Nbr_Elements);

   --  True if LIST is empty.
   function Is_Empty (List : List_Type) return Boolean;

   --  Iterator.  The idiomatic way to iterate is:
   --  It := Iterate (List);
   --  while Is_Valid (It) loop
   --     El := Get_Element (It);
   --     ...
   --     Next (It);
   --  end loop;
   type Iterator is private;

   function Iterate (List : List_Valid_Type) return Iterator;
   function Is_Valid (It : Iterator) return Boolean;
   procedure Next (It : in out Iterator);
   function Get_Element (It : Iterator) return El_Type;
   procedure Set_Element (It : Iterator; El : El_Type);

   --  Use the C convention for all these subprograms, so that the Iterator is
   --  always passed by reference.
   pragma Convention (C, Is_Valid);
   pragma Convention (C, Next);
   pragma Convention (C, Get_Element);
   pragma Convention (C, Set_Element);

   --  Like Iterate, but if LIST is Null_List, it returns an iterator that is
   --  never valid.
   function Iterate_Safe (List : List_Type) return Iterator;

private
   type Chunk_Index_Type is new Int32;
   for Chunk_Index_Type'Size use 32;
   No_Chunk_Index : constant Chunk_Index_Type := 0;

   Chunk_Len : constant := 7;

   type Node_Type_Array is
     array (Nat32 range 0 .. Chunk_Len - 1) of El_Type;

   type Chunk_Type is record
      Next : Chunk_Index_Type;
      Els : Node_Type_Array;
   end record;

   type Iterator is record
      Chunk : Chunk_Index_Type;
      Chunk_Idx : Nat32;
      Remain : Nat32;
   end record;
   pragma Convention (C, Iterator);

   pragma Inline (Iterate);
   pragma Inline (Is_Valid);
   pragma Inline (Next);
   pragma Inline (Get_Element);
end Lists;