comp.lang.ada
 help / color / mirror / Atom feed
From: Brian Drummond <brian_drummond@btconnect.com>
Subject: Newbie-ish question about generics and Ada.Streams
Date: Mon, 27 Dec 2010 17:23:53 +0000
Date: 2010-12-27T17:23:53+00:00	[thread overview]
Message-ID: <ohhhh6tr9nit36daakg9m0i6bgq4ug3knp@4ax.com> (raw)

Season's greetings!

In between rounds of turkey, I have been trying to learn a bit more about generics, though it still
feels as if I am pushing on a rope.

In particular, I have been trying to use generic procedures for stream access for a large set of
similar data types (enumerations) where I want a specific representation in the output file. This
means attaching the Read and Write procedures - instantiated generics - to the types using
representation clauses.

Which (as I understand it) has to be done before the types are frozen....

I hope the example below is clear...

Comments welcome, but the specific points I am unhappy with are:

(1) The incomplete procedure declarations, with deferred implementation. 
I suspect there is no way around this, as long as I need to freeze the type 
before the procedure body.

(2) The second generic parameter - the named array type. It feels like I am missing 
something obvious here, and there ought to be a way to avoid adding this clutter.

(3) Instantiating the generic under a different name, and renaming to match the incomplete
declaration. Is this (a) necessary, (b) Gnat-specific, or (c) something stupid on my part?

Thanks,
- Brian


with Ada.Text_Io.Text_Streams;
with Ada.Streams;

procedure try_generics is

-- We have multiple enumerations...
type shape is (circle, square);
type colour is (red, green, blue);

-- and we want to control how they are written to a stream
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour);
procedure shape_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in shape);
for colour'write use colour_write;
for shape'write use shape_write;

-- In this example, we use an array of strings indexed by the enumerations.
-- shapes : constant array(shape) of string(1 .. 7) := ("circle ", "square ");
-- but... generics (below) seem picky about using named vs anonymous subtypes
subtype name is string(1 .. 7);
type shape_names is array(shape) of name;
type colour_names is array(colour) of name;
-- appears to freeze the types; write procedures or representation clauses after this are "too late"
shapes : constant shape_names := ("circle ", "square ");
colours : constant colour_names := ("red    ", "green  ", "blue   ");

-- Example body of a write procedure...
--procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour) is
--begin
--   String'write(Stream, colours(what));
--end colour_write;

-- That would get repetitive, so let's use a generic...
   generic
      type Item_Type is (<>);
      type Item_Names(<>) is array(Item_Type) of name;
      -- Feels as if the Item_Names type declaration ought to be unnecessary...
      Names : Item_Names;
   procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			Item : in Item_Type);

   procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			Item : in Item_Type) is
   begin
      String'Write(Stream, Names(Item));
   end Enum_Write;

-- And instantiate it. First attempt...
--procedure shape_write is new Enum_Write(Item_Type => shape, 
			Item_Names => shape_names, Names => shapes);
--try_generics.adb:12:01: missing body for "shape_write"
--try_generics.adb:43:11: instantiation cannot provide body for "shape_write"

-- So instantiate it under a different name, and rename it...
procedure shape_writer is new Enum_Write(Item_Type => shape, 
			Item_Names => shape_names, Names => shapes);
procedure shape_write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in shape) renames shape_writer;
procedure colour_writer is new Enum_Write(Item_Type => colour, 
			Item_Names => colour_names, Names =>colours);
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour) renames colour_writer;
-- That duplication is ugly ... can this be simplified?

-- Now we can use the enumerations in a toy block
type toy_block is record
   my_colour : colour;
   my_shape : shape;
end record;

-- and output the block to a stream
my_block : constant toy_block := (my_colour => red, my_shape => square);
Stdout : Ada.Text_Io.Text_Streams.Stream_Access :=
Ada.Text_Io.Text_Streams.Stream(Ada.Text_Io.Current_Output);
begin
   toy_block'write(Stdout, my_block); 
end try_generics;





             reply	other threads:[~2010-12-27 17:23 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-27 17:23 Brian Drummond [this message]
2010-12-27 18:59 ` Newbie-ish question about generics and Ada.Streams Robert A Duff
2010-12-27 23:26   ` Brian Drummond
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox