-- In the optimized case, we make use of these:
- -- procedure Next (Position : in out Cursor); -- instead of Iter.Next
+ -- procedure _Next (Position : in out Cursor); -- instead of Iter.Next
+ -- (or _Previous for reverse loops)
-- function Pseudo_Reference
-- (Container : aliased Vector'Class) return Reference_Control_Type;
-- pollute the namespace for clients. The compiler has no trouble breaking
-- privacy to call things in the private part of an instance.)
+ -- Note that Next and Previous are renamed as _Next and _Previous with
+ -- leading underscores. Leading underscores are illegal in Ada, but we
+ -- allow them in the run-time library. This allows us to avoid polluting
+ -- the user-visible namespaces.
+
-- Source:
-- for X of My_Vector loop
-- X.Count := X.Count + 1;
-- ...
--
- -- Next (Cur); -- or Prev
+ -- _Next (Cur); -- or _Previous
-- -- This is instead of "Cur := Next (Iter, Cur);"
-- end;
-- -- No finalization here
Stats : List_Id := Statements (N);
-- Maybe wrapped in a conditional if a filter is present
- Cursor : Entity_Id;
- Decl : Node_Id;
- Iter_Type : Entity_Id;
- Iterator : Entity_Id;
- Name_Init : Name_Id;
- Name_Step : Name_Id;
- New_Loop : Node_Id;
+ Cursor : Entity_Id;
+ Decl : Node_Id;
+ Iter_Type : Entity_Id;
+ Iterator : Entity_Id;
+ Name_Init : Name_Id;
+ Name_Step : Name_Id;
+ Name_Fast_Step : Name_Id;
+ New_Loop : Node_Id;
Fast_Element_Access_Op : Entity_Id := Empty;
Fast_Step_Op : Entity_Id := Empty;
if Reverse_Present (I_Spec) then
Name_Init := Name_Last;
Name_Step := Name_Previous;
+ Name_Fast_Step := Name_uPrevious;
else
Name_Init := Name_First;
Name_Step := Name_Next;
+ Name_Fast_Step := Name_uNext;
end if;
-- The type of the iterator is the return type of the Iterate function
Iter_Pack := Scope (Root_Type (Etype (Iter_Type)));
- -- Find declarations needed for "for ... of" optimization
+ -- Find declarations needed for "for ... of" optimization.
-- These declarations come from GNAT sources or sources
-- derived from them. User code may include additional
-- overloadings with similar names, and we need to perforn
-- some reasonable resolution to find the needed primitives.
- -- It is unclear whether this mechanism is fragile if a user
- -- makes arbitrary changes to the private part of a package
- -- that supports iterators.
+ -- Note that we use _Next or _Previous to avoid picking up
+ -- some arbitrary user-defined Next or Previous.
Ent := First_Entity (Pack);
while Present (Ent) loop
-- Next or Prev procedure with one parameter called
-- Position.
- elsif Chars (Ent) = Name_Step
- and then Ekind (Ent) = E_Procedure
- and then Present (First_Formal (Ent))
- and then Chars (First_Formal (Ent)) = Name_Position
- and then No (Next_Formal (First_Formal (Ent)))
- then
+ elsif Chars (Ent) = Name_Fast_Step then
pragma Assert (No (Fast_Step_Op));
Fast_Step_Op := Ent;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased List'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
Item : out Reference_Type);
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
function Pseudo_Reference
(Container : aliased Tree'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased List'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased List'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
function Pseudo_Reference
(Container : aliased Tree'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Vector'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Vector'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
function Pseudo_Reference
(Container : aliased Tree'Class) return Reference_Control_Type;
for Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Exp_Ch5 for
- -- details.
+ -- Three operations are used to optimize the expansion of "for ... of"
+ -- loops: the Next(Cursor) (or Previous) procedure in the visible part,
+ -- and the following Pseudo_Reference and Get_Element_Access functions.
+ -- See Exp_Ch5 for details, including the leading underscores here.
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Vector'Class) return Reference_Control_Type;
for Reference_Type'Write use Write;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Map'Class) return Reference_Control_Type;
for Constant_Reference_Type'Read use Read;
- -- Three operations are used to optimize in the expansion of "for ... of"
- -- loops: the Next(Cursor) procedure in the visible part, and the following
- -- Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
- -- details.
+ -- See Ada.Containers.Vectors for documentation on the following
+
+ procedure _Next (Position : in out Cursor) renames Next;
+ procedure _Previous (Position : in out Cursor) renames Previous;
function Pseudo_Reference
(Container : aliased Set'Class) return Reference_Control_Type;
with Csets; use Csets;
with Errout; use Errout;
with Hostparm; use Hostparm;
+with Lib; use Lib;
with Namet; use Namet;
with Opt; use Opt;
with Sinput; use Sinput;
-- Underline character
when '_' =>
- Error_Msg_S ("identifier cannot start with underline");
+ -- Identifiers with leading underscores are not allowed in Ada.
+ -- However, we allow them in the run-time library, so we can
+ -- create names that are hidden from normal Ada code. For an
+ -- example, search for "Name_uNext", which is "_Next".
+
+ if not In_Internal_Unit (Scan_Ptr) then
+ Error_Msg_S ("identifier cannot start with underline");
+ end if;
+
Name_Len := 1;
Name_Buffer (1) := '_';
Scan_Ptr := Scan_Ptr + 1;
Name_Has_Element : constant Name_Id := N + $;
Name_Forward_Iterator : constant Name_Id := N + $;
Name_Reversible_Iterator : constant Name_Id := N + $;
+ Name_uNext : constant Name_Id := N + $;
Name_Previous : constant Name_Id := N + $;
+ Name_uPrevious : constant Name_Id := N + $;
Name_Pseudo_Reference : constant Name_Id := N + $;
Name_Reference_Control_Type : constant Name_Id := N + $;
Name_Get_Element_Access : constant Name_Id := N + $;