Skip to content

Instantly share code, notes, and snippets.

@flyx
Created February 23, 2021 20:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flyx/70abba5548474ceabc838f288e34daa9 to your computer and use it in GitHub Desktop.
Save flyx/70abba5548474ceabc838f288e34daa9 to your computer and use it in GitHub Desktop.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Hashed_Maps; use Ada.Containers;
with Ada.Iterator_Interfaces;
procedure Main is
package Tiles is
-- Implementation is completely hidden
type Tile_Type is private;
type Cursor is private;
type Tile_Set is tagged private
with Default_Iterator => Iterate,
Iterator_Element => Tile_Type,
Constant_Indexing => Constant_Reference;
function Has_Element (Position: Cursor) return Boolean;
package Tile_Set_Iterator_Interfaces is new
Ada.Iterator_Interfaces (Cursor, Has_Element);
type Constant_Reference_Type
(Element : not null access constant Tile_Type) is null record
with Implicit_Dereference => Element;
function Iterate (Container: in Tile_Set) return
Tile_Set_Iterator_Interfaces.Forward_Iterator'Class;
function Constant_Reference (Container : aliased in Tile_Set;
Position : Cursor)
return Constant_Reference_Type;
type Tile_Key is private;
procedure Add (Collection : in out Tile_Set; Tile : Tile_Type);
function Get (Collection : in Tile_Set; Key : Natural) return Tile_Type;
function Make (Key : Natural; Data : Integer) return Tile_Type;
function Image (Tile : Tile_Type) return String;
private
type Tile_Key is record
X : Natural;
end record;
function Tile_Hash (K : Tile_Key) return Hash_Type is
(Hash_Type (K.X));
type Tile_Type is record
Key : Tile_Key;
Data : Integer;
end record;
package Tile_Matrix is new Ada.Containers.Hashed_Maps
(Element_Type => Tile_Type,
Key_Type => Tile_Key,
Hash => Tile_Hash,
Equivalent_Keys => "=");
use Tile_Matrix;
type Tile_Set is tagged record
Data : aliased Tile_Matrix.Map;
end record;
type Cursor is record
Data : Tile_Matrix.Cursor;
end record;
end Tiles;
package body Tiles is
type Iterator_Type (Data : access constant Tile_Matrix.Map) is new Tile_Set_Iterator_Interfaces.Forward_Iterator with null record;
function First (Object : Iterator_Type) return Cursor is
(Cursor'(Data => Object.Data.Iterate.First));
function Next (Object : Iterator_Type; Position : Cursor) return Cursor is
(Cursor'(Data => Object.Data.Iterate.Next (Position.Data)));
function Has_Element (Position: Cursor) return Boolean is
(Tile_Matrix.Has_Element (Position.Data));
function Iterate (Container: in Tile_Set) return
Tile_Set_Iterator_Interfaces.Forward_Iterator'Class is
(Iterator_Type'(Data => Container.Data'Access));
function Constant_Reference (Container : aliased in Tile_Set;
Position : Cursor)
return Constant_Reference_Type is
(Constant_Reference_Type'(Element => Container.Data.Constant_Reference (Position.Data).Element));
procedure Add (Collection : in out Tile_Set; Tile : Tile_Type) is
begin
Collection.Data.Include (Key => Tile.Key, New_Item => Tile);
end Add;
function Get (Collection : in Tile_Set; Key : Natural) return Tile_Type is
K : Tile_Key := (X => Key);
C : Tile_Matrix.Cursor := Collection.Data.Find (Key => K);
begin -- For illustration, would need to handle missing keys
return Result : Tile_Type do
Result := Collection.Data (C);
end return;
end Get;
function Image (Tile : Tile_Type) return String is
(Tile.Key.X'Image & '=' & Tile.Data'Image);
function Make (Key : Natural; Data : Integer) return Tile_Type is
New_Key : Tile_Key := (X => Key);
begin
return Result : Tile_Type do
Result.Key := New_Key;
Result.Data := Data;
end return;
end Make;
end Tiles;
use Tiles;
S : Tile_Set;
T : Tile_Type;
begin
S.Add (Make (Key => 1, Data => 10));
T := S.Get (1);
Put_Line (Image (T)); -- 1, 10
S.Add (Make (Key => 2, Data => 20));
T := S.Get (2);
Put_Line (Image (T)); -- 1, 20
for X of S loop
Put_Line (Image (X));
end loop;
end Main;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment