From 4b87cb60d043c0765e5547a3a08f2ff48d7af6ea Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Thu, 16 Apr 2020 14:55:56 +1000 Subject: Basic outline of Nim CountTables in Ada --- misc/count_tables.adb | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ misc/count_tables.ads | 124 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 misc/count_tables.adb create mode 100644 misc/count_tables.ads diff --git a/misc/count_tables.adb b/misc/count_tables.adb new file mode 100644 index 0000000..68cb9ad --- /dev/null +++ b/misc/count_tables.adb @@ -0,0 +1,139 @@ + +package body Count_Tables is + + + function Has_Element + (Position : Cursor) + return Boolean is + begin + return Position.My_Map /= null and then + Position.Index >= Position.My_Map.My_Vec.First_Index and then + Position.Index <= Position.My_Map.My_Vec.Last_Index; + end Has_Element; + + + function Key + (Position : Cursor) + return Key_Type is + begin + return Internal_Maps.Key + (Position.My_Map.My_Vec.Element (Position.Index)); + end Key; + + + function Element + (Position : Cursor) + return Natural is + begin + return Internal_Maps.Element + (Position.My_Map.My_Vec.Element (Position.Index)); + end Element; + + + function Reference + (Container : aliased in out Map; + Position : Cursor) + return Reference_Type is + begin + return (Element => Container.My_Map.Reference + (Container.My_Vec (Position.Index)).Element); + end Reference; + + + procedure Increment + (Container : in out Map; + Key : in Key_Type; + Value : in Natural := 1) + is + Place : Internal_Maps.Cursor; + Success : Boolean; + begin + Container.My_Map.Insert (Key, Value, Place, Success); + if not Success then + Container.My_Map.Reference (Key) := Container.My_Map.Reference (Key) + Value; + else + Container.My_Vec.Append (Place); + end if; + end Increment; + + + function Less + (Left, Right : in Internal_Maps.Cursor) + return Boolean is + begin + return Internal_Maps.Element (Right) < Internal_Maps.Element (Left); + end Less; + + + procedure Sort + (Container : in out Map) is + begin + Cursor_Sorting.Sort (Container.My_Vec); + end Sort; + + + function Iterate + (Container : in Map) + return Map_Iterator_Interfaces.Reversible_Iterator'Class is + begin + return It : Iterator := (Ada.Finalization.Limited_Controlled + with Container => Container'Unrestricted_Access); + end Iterate; + + + function First + (Object : in Iterator) return Cursor is + begin + if Object.Container /= null and then + not Object.Container.My_Map.Is_Empty + then + return (My_Map => Object.Container, Index => 1); + else + return No_Element; + end if; + end First; + + + function Last + (Object : in Iterator) return Cursor is + begin + if Object.Container /= null and then + not Object.Container.My_Map.Is_Empty + then + return (My_Map => Object.Container, Index => Object.Container.My_Vec.Last_Index); + else + return No_Element; + end if; + end Last; + + + function Next + (Object : in Iterator; + Position : in Cursor) return Cursor is + begin + if Has_Element (Position) and then + Position.Index < Position.My_Map.My_Vec.Last_Index + then + return (My_Map => Position.My_Map, Index => Position.Index + 1); + else + return No_Element; + end if; + end Next; + + + function Previous + (Object : in Iterator; + Position : in Cursor) return Cursor is + begin + if Has_Element (Position) and then + Position.Index > Position.My_Map.My_Vec.First_Index + then + return (My_Map => Position.My_Map, Index => Position.Index - 1); + else + return No_Element; + end if; + end Previous; + + +end Count_Tables; + diff --git a/misc/count_tables.ads b/misc/count_tables.ads new file mode 100644 index 0000000..9f3055c --- /dev/null +++ b/misc/count_tables.ads @@ -0,0 +1,124 @@ + + +with + Ada.Iterator_Interfaces; + +private with + Ada.Containers.Indefinite_Ordered_Maps, + Ada.Containers.Vectors, + Ada.Finalization; + +generic + type Key_Type (<>) is private; + with function "<" (Left, Right : Key_Type) return Boolean is <>; +package Count_Tables is + + -- This package imitates the basics of + -- the Nim CountTable table variant. + + -- Functionality is incomplete and likely inefficient, + -- as this was only put together for demonstrative purposes. + + type Map is tagged private + with Variable_Indexing => Reference, + Default_Iterator => Iterate, + Iterator_Element => Natural; + + type Cursor is private; + + Empty_Map : constant Map; + No_Element : constant Cursor; + + function Has_Element + (Position : Cursor) + return Boolean; + + function Key + (Position : Cursor) + return Key_Type; + + function Element + (Position : Cursor) + return Natural; + + package Map_Iterator_Interfaces is new + Ada.Iterator_Interfaces (Cursor, Has_Element); + + type Reference_Type (Element : not null access Natural) is private + with Implicit_Dereference => Element; + + function Reference + (Container : aliased in out Map; + Position : Cursor) + return Reference_Type; + + procedure Increment + (Container : in out Map; + Key : in Key_Type; + Value : in Natural := 1); + + procedure Sort + (Container : in out Map); + + function Iterate + (Container : in Map) + return Map_Iterator_Interfaces.Reversible_Iterator'Class; + +private + + type Map_Access is access all Map; + + type Cursor is record + My_Map : Map_Access; + Index : Positive; + end record; + + package Internal_Maps is new Ada.Containers.Indefinite_Ordered_Maps (Key_Type, Natural); + package Cursor_Vectors is new Ada.Containers.Vectors (Positive, Internal_Maps.Cursor, Internal_Maps."="); + + type Map is tagged record + My_Map : Internal_Maps.Map; + My_Vec : Cursor_Vectors.Vector; + end record; + + Empty_Map : constant Map := + (My_Map => Internal_Maps.Empty_Map, + My_Vec => Cursor_Vectors.Empty_Vector); + No_Element : constant Cursor := + (My_Map => null, + Index => 1); + + function Less + (Left, Right : in Internal_Maps.Cursor) + return Boolean; + + package Cursor_Sorting is new Cursor_Vectors.Generic_Sorting (Less); + + type Reference_Type (Element : not null access Natural) is null record; + + type Iterator is new Ada.Finalization.Limited_Controlled and + Map_Iterator_Interfaces.Reversible_Iterator with + record + Container : Map_Access; + end record; + + overriding function First + (Object : in Iterator) + return Cursor; + + overriding function Last + (Object : in Iterator) + return Cursor; + + overriding function Next + (Object : in Iterator; + Position : in Cursor) + return Cursor; + + overriding function Previous + (Object : in Iterator; + Position : in Cursor) + return Cursor; + +end Count_Tables; + -- cgit