comp.lang.ada
 help / color / mirror / Atom feed
* Run-Time Type Assignment
@ 2002-08-28  6:53 Robert C. Leif
  2002-08-28 11:04 ` Robert Dewar
                   ` (3 more replies)
  0 siblings, 4 replies; 33+ messages in thread
From: Robert C. Leif @ 2002-08-28  6:53 UTC (permalink / raw)


From: Bob Leif
To: Fellow readers of Comp.Lang.Ada
Introduction: Cytometry instruments are employed for blood cell counts
and measuring parameters related to cancer and other diseases. I am now
trying to create a binary file for my work on CytometryML. CytometryML
is a collection of XML schemas that will be used for cytometry data. The
original Flow Cytometry Standard and its implementations permitted the
operator of an instrument at run-time to select both the number of
parameters and types of parameters to be used as elements in a record.
Each instrument has a maximum number of parameters. The data types for
these parameters were already compiled. An array of these records was
then created from the instrument's measurements and subsequently stored.
I am not defending the inclusion of this capability in a clinical
instrument. However, it is perceived as required for a research
instrument. The maximum number of records that I have specified for
CytometryML is two billion. Therefore, the implementation should be
space efficient.
Problem: Two possible approaches for the creation of this record are to
use a tagged record or a variant record. I do not know how to select a
subtype of a class at run-time. The variant record approach possibly
would have worked in Pascal; however, it did not compile in the
cost-free GNAT compiler.
---------------------------------------------------
--Variant Record Approach
--Does not work
   type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters :
Num_Parameters_Type) is --range 1..2
   record
      case Num_Parameters  is
         when 1 =>
            Parameter_1: Parameter_1_Type;
         when 2 =>
            Parameter_1: Parameter_1_Type;
 		--Parameter_1 conflicts with declaration 2 lines above.
            --Can not have the same signature as the one above.
            Parameter_2: Parameter_2_Type;         
      end case;
   end record;

-----------------------------------------------------
-- tagged record
package Array_Of_Records_Class_Pkg is new Array_Of_Records_G_Pkg(
   Length      => Num_Of_Records,   
   Record_Type => Record_Type'Class); 
--Bombs because "Actual for "Record_Type" must be a definitive subtype"
--How can I make this dispatch based the Num_Parameters?
---------------------------------------------------
One unconventional approach, which because of the increase in computer
speed might now work, is at run-time to create the small amount of Ada
code needed, compile it, and link it. The user need not be aware of this
possibly bizarre approach. 

My application may have some generality because this type of type
assignment (for want of a better term) conceivably could be used for
spreadsheets and data bases. This is not a recommendation.
Thank you.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28  6:53 Robert C. Leif
@ 2002-08-28 11:04 ` Robert Dewar
  2002-08-28 13:35   ` Robert A Duff
  2002-08-28 13:41 ` Robert A Duff
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 33+ messages in thread
From: Robert Dewar @ 2002-08-28 11:04 UTC (permalink / raw)


"Robert C. Leif" <rleif@rleif.com> wrote in message news:<mailman.1030517642.16877.comp.lang.ada@ada.eu.org>...
> The variant record approach possibly
> would have worked in Pascal; however, it did not compile in the
> cost-free GNAT compiler.

The approach could work fine, but obviously the compiler would be
expected to reject the illegal Ada code you fed into it (this does
not haave to do with "cost-free", it has to do with rules in the RM :-)

it is of course the case that anything you can do in Pascal
can easily be done in Ada



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
       [not found] <002a01c24e5f$9ee347b0$789a0844@robertqgx6k4x9>
@ 2002-08-28 11:33 ` sk
       [not found] ` <3D6CB4F5.F4E05D76@myob.com>
  1 sibling, 0 replies; 33+ messages in thread
From: sk @ 2002-08-28 11:33 UTC (permalink / raw)


Hi, 

> type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters : Num_Parameters_Type) is --range 1..2
>   record
>      case Num_Parameters  is
>         when 1 =>
>            Parameter_1: Parameter_1_Type;
>         when 2 =>
>            Parameter_1: Parameter_1_Type;
>                --Parameter_1 conflicts with declaration 2 lines above.
>            --Can not have the same signature as the one above.
>            Parameter_2: Parameter_2_Type;         
>      end case;
>   end record;

type Disc_Rec ( Disc : Disc_Type) is record 

    Parm1 : Parm1_Type;

    case Disc is
        when 1 => null;
        when 2 => 
            Parm2 L Parm2_Type;
    end case;

end record;

Put common parameters in "common" area of record.

-- 
-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
-------------------------------------



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
       [not found] ` <3D6CB4F5.F4E05D76@myob.com>
@ 2002-08-28 11:37   ` sk
  2002-08-28 15:39   ` Robert C. Leif
  2002-08-28 20:54   ` Robert C. Leif
  2 siblings, 0 replies; 33+ messages in thread
From: sk @ 2002-08-28 11:37 UTC (permalink / raw)


Hi,

NOT "Parm2 L Parm2_Type;"

==> "Parm2 : Parm2_Type;"

The colon and "L" being mm's apart ...

-- 
-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
-------------------------------------



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 11:04 ` Robert Dewar
@ 2002-08-28 13:35   ` Robert A Duff
  2002-08-28 14:56     ` Larry Kilgallen
  0 siblings, 1 reply; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 13:35 UTC (permalink / raw)


dewar@gnat.com (Robert Dewar) writes:

> it is of course the case that anything you can do in Pascal
> can easily be done in Ada

downward closures

tagless variant records

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28  6:53 Robert C. Leif
  2002-08-28 11:04 ` Robert Dewar
@ 2002-08-28 13:41 ` Robert A Duff
  2002-08-28 17:15 ` Hyman Rosen
  2002-08-28 20:27 ` Björn Lundin
  3 siblings, 0 replies; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 13:41 UTC (permalink / raw)


"Robert C. Leif" <rleif@rleif.com> writes:

> --Variant Record Approach
> --Does not work
>    type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters :
> Num_Parameters_Type) is --range 1..2
>    record
>       case Num_Parameters  is
>          when 1 =>
>             Parameter_1: Parameter_1_Type;
>          when 2 =>
>             Parameter_1: Parameter_1_Type;
>  		--Parameter_1 conflicts with declaration 2 lines above.

So change the name.  Or combine into one field outside the variant part,
as suggested in another note.

Same-named record fields are illegal in Pascal, too, by the way.

> -- tagged record
> package Array_Of_Records_Class_Pkg is new Array_Of_Records_G_Pkg(
>    Length      => Num_Of_Records,   
>    Record_Type => Record_Type'Class); 
> --Bombs because "Actual for "Record_Type" must be a definitive subtype"
> --How can I make this dispatch based the Num_Parameters?

You don't show the generic, so I can't tell what you're trying to do,
but Record_Type has to have (<>) discriminants to allow an indefinite
actual.  (Roughly speaking, "indefinite" means that different objects of
the subtype will have different sizes -- which is true of T'Class.)

If your goal is to have an array of different-sized components,
that's not directly allowed in Ada.  You need some form of indirection,
or some such thing.

If you change the variant record above to have a defaulted discriminant,
then you can create an array of them, but they will be allocated the max
size in most compilers.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 14:56     ` Larry Kilgallen
@ 2002-08-28 14:31       ` Robert A Duff
  2002-08-28 14:59         ` Lutz Donnerhacke
  2002-08-28 18:03         ` Frank J. Lhota
  0 siblings, 2 replies; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 14:31 UTC (permalink / raw)


Kilgallen@SpamCop.net (Larry Kilgallen) writes:

> What is a downward closure ?

The ability to pass a procedure as a parameter to a procedure.
The "downward" means the closure is passed "down" from caller to
callee.  This is more restrictive than the "full closures" which are
found in Lisp and many other languages of that ilk; a full closure may
be *returned* from a procedure, and may be assigned into a variable.

GNAT supports downward closures via the 'Unrestricted_Access attribute,
but that's not Ada (unfortunately).

In Pascal, downward closures are very useful for making iterators and
other user-defined control structures.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 13:35   ` Robert A Duff
@ 2002-08-28 14:56     ` Larry Kilgallen
  2002-08-28 14:31       ` Robert A Duff
  0 siblings, 1 reply; 33+ messages in thread
From: Larry Kilgallen @ 2002-08-28 14:56 UTC (permalink / raw)


In article <wccvg5vhzsp.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
> dewar@gnat.com (Robert Dewar) writes:
> 
>> it is of course the case that anything you can do in Pascal
>> can easily be done in Ada
> 
> downward closures

What is a downward closure ?

> tagless variant records



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 14:31       ` Robert A Duff
@ 2002-08-28 14:59         ` Lutz Donnerhacke
  2002-08-28 22:32           ` Robert A Duff
  2002-08-29 22:55           ` Dmitry A.Kazakov
  2002-08-28 18:03         ` Frank J. Lhota
  1 sibling, 2 replies; 33+ messages in thread
From: Lutz Donnerhacke @ 2002-08-28 14:59 UTC (permalink / raw)


* Robert A Duff wrote:
>Kilgallen@SpamCop.net (Larry Kilgallen) writes:
>> What is a downward closure ?
>
>The ability to pass a procedure as a parameter to a procedure.
>The "downward" means the closure is passed "down" from caller to
>callee.  This is more restrictive than the "full closures" which are
>found in Lisp and many other languages of that ilk; a full closure may
>be *returned* from a procedure, and may be assigned into a variable.
>
>GNAT supports downward closures via the 'Unrestricted_Access attribute,
>but that's not Ada (unfortunately).
>
>In Pascal, downward closures are very useful for making iterators and
>other user-defined control structures.

In Ada you use generics for this.



^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: Run-Time Type Assignment
       [not found] ` <3D6CB4F5.F4E05D76@myob.com>
  2002-08-28 11:37   ` sk
@ 2002-08-28 15:39   ` Robert C. Leif
  2002-08-28 18:53     ` Jeffrey Carter
  2002-08-28 20:54   ` Robert C. Leif
  2 siblings, 1 reply; 33+ messages in thread
From: Robert C. Leif @ 2002-08-28 15:39 UTC (permalink / raw)


From: Bob Leif
To: SK et al.
How does your solution work, if the variants are:
case Num_Parameters  is
  when 1 =>
    Parameter_1: Parameter_1_Type;
  when 2 =>
    Parameter_1: Parameter_1_Type;
    Parameter_2: Parameter_2_Type;
  when 3 =>
    Parameter_1: Parameter_1_Type;
    Parameter_2: Parameter_2_Type;
    Parameter_3: Parameter_3_Type;
end case;
This is the equivalent of a tagged type. Each succeeding variant
includes all of its predecessor and one new element. I have made it work
by defining new record types that include the elements for each variant.
However, this is cumbersome. I will be testing the other suggestions.
Thank you.
-----Original Message-----
From: comp.lang.ada-admin@ada.eu.org
[mailto:comp.lang.ada-admin@ada.eu.org] On Behalf Of sk
Sent: Wednesday, August 28, 2002 4:33 AM
To: comp.lang.ada@ada.eu.org
Subject: Re: Run-Time Type Assignment

Hi, 

> type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters :
Num_Parameters_Type) is --range 1..2
>   record
>      case Num_Parameters  is
>         when 1 =>
>            Parameter_1: Parameter_1_Type;
>         when 2 =>
>            Parameter_1: Parameter_1_Type;
>                --Parameter_1 conflicts with declaration 2 lines above.
>            --Can not have the same signature as the one above.
>            Parameter_2: Parameter_2_Type;         
>      end case;
>   end record;

type Disc_Rec ( Disc : Disc_Type) is record 

    Parm1 : Parm1_Type;

    case Disc is
        when 1 => null;
        when 2 => 
            Parm2 L Parm2_Type;
    end case;

end record;

Put common parameters in "common" area of record.

-- 
-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
-------------------------------------




^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
       [not found] <005101c24ea9$0de9c960$789a0844@robertqgx6k4x9>
@ 2002-08-28 16:06 ` sk
  2002-08-28 22:44   ` tmoran
  2002-08-29  0:37   ` tmoran
  0 siblings, 2 replies; 33+ messages in thread
From: sk @ 2002-08-28 16:06 UTC (permalink / raw)


Hi,

Without knowing exactly what you are wanting to do 
(the complex nesting of types would make me consider 
about rethinking my data modeling), try this 
(compiles Linux 3.14p. Also q&d so don't know how 
usable this is).

---------------------------------------------------------

procedure xxxx is 

    type Base_Type is abstract tagged null record;

    type Parm1_Type is new Natural;
    type Parm2_Type is new Character;
    type Parm3_Type is new Integer;

    type Level_One is new Base_Type with record
        Parm1 : Parm1_Type;
    end record;
    
    type Level_Two is new Level_One with record
        Parm2 : Parm2_Type;
    end record;
    
    type Level_Three is new Level_Two with record
        Parm3 : Parm3_Type;
    end record;

    type Base_Access is access all Base_Type;

    type Main_Type (Parms : Base_Access) is null record;

begin
    null;
end xxxx;

-- 
-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
-------------------------------------



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28  6:53 Robert C. Leif
  2002-08-28 11:04 ` Robert Dewar
  2002-08-28 13:41 ` Robert A Duff
@ 2002-08-28 17:15 ` Hyman Rosen
  2002-08-28 20:27 ` Björn Lundin
  3 siblings, 0 replies; 33+ messages in thread
From: Hyman Rosen @ 2002-08-28 17:15 UTC (permalink / raw)


Robert C. Leif wrote:
 > I am now trying to create a binary file for my work on CytometryML.
 > CytometryML is a collection of XML schemas that will be used for
 > cytometry data.

Isn't XML a text format? Why are you creating a binary file?

 > The maximum number of records that I have specified for CytometryML
 > is two billion.

Are you making the specification, or is this the specification you
have been given? Are the records so interlinked that you must process
all of them at once?

> Two possible approaches for the creation of this record

Creation of what record? Didn't you say that the file of data
already exists? Are you trying to read in the data to process it?
What is the format of the data in the file? This all seems very
confusing to me. I don't think you have correctly explained what
it is that you need.

> My application may have some generality because this type of type
> assignment (for want of a better term) conceivably could be used for
> spreadsheets and data bases.

What in the world does this mean?

> This is not a recommendation.

Or this?




^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 14:31       ` Robert A Duff
  2002-08-28 14:59         ` Lutz Donnerhacke
@ 2002-08-28 18:03         ` Frank J. Lhota
  2002-08-28 18:37           ` Pat Rogers
  2002-08-28 22:47           ` Robert A Duff
  1 sibling, 2 replies; 33+ messages in thread
From: Frank J. Lhota @ 2002-08-28 18:03 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccn0r7hx5y.fsf@shell01.TheWorld.com...
> Kilgallen@SpamCop.net (Larry Kilgallen) writes:
>
> > What is a downward closure ?
>
> The ability to pass a procedure as a parameter to a procedure.

<snip>

> GNAT supports downward closures via the 'Unrestricted_Access attribute,
> but that's not Ada (unfortunately).

What about using just the plain old 'Access attribute to pass a pointer to
the procedure as a parameter? That is supported by all Ada 95 compilers.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 18:03         ` Frank J. Lhota
@ 2002-08-28 18:37           ` Pat Rogers
  2002-08-28 22:47           ` Robert A Duff
  1 sibling, 0 replies; 33+ messages in thread
From: Pat Rogers @ 2002-08-28 18:37 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message
news:Jf8b9.15221$zT.6491@nwrddc04.gnilink.net...
> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> news:wccn0r7hx5y.fsf@shell01.TheWorld.com...
> > Kilgallen@SpamCop.net (Larry Kilgallen) writes:
> >
> > > What is a downward closure ?
> >
> > The ability to pass a procedure as a parameter to a procedure.
>
> <snip>
>
> > GNAT supports downward closures via the 'Unrestricted_Access
attribute,
> > but that's not Ada (unfortunately).
>
> What about using just the plain old 'Access attribute to pass a
pointer to
> the procedure as a parameter? That is supported by all Ada 95
compilers.

The accessibility rules prevent that approach in the general case.

Do a search -- this topic is well covered!


--
Patrick Rogers                       Consulting and Training in:
http://www.classwide.com       Real-Time/OO Languages
progers@classwide.com          Hard Deadline Schedulability Analysis
(281)648-3165                            Software Fault Tolerance





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 15:39   ` Robert C. Leif
@ 2002-08-28 18:53     ` Jeffrey Carter
  0 siblings, 0 replies; 33+ messages in thread
From: Jeffrey Carter @ 2002-08-28 18:53 UTC (permalink / raw)


"Robert C. Leif" wrote:
> 
> From: Bob Leif
> To: SK et al.
> How does your solution work, if the variants are:
> case Num_Parameters  is
>   when 1 =>
>     Parameter_1: Parameter_1_Type;
>   when 2 =>
>     Parameter_1: Parameter_1_Type;
>     Parameter_2: Parameter_2_Type;
>   when 3 =>
>     Parameter_1: Parameter_1_Type;
>     Parameter_2: Parameter_2_Type;
>     Parameter_3: Parameter_3_Type;
> end case;
> This is the equivalent of a tagged type.

One way is to make it a tagged type with a chain of types extended from
it. If you need/want to avoid tagged types, the composition equivalent
to type extension is to build up a bunch of record types, then combine
them in a variant record:

type Param_1_Data is record
   Parameter_1 : Parameter_1_Type;
end record;

-- Further types may be in separate packages if desired
type Param_2_Data is record
   Parent : Param_1_Data;
   Parameter_2 : Parameter_2_Type;
end record;

type Param_3_Data is record
   Parent : Param_2_Data;
   Parameter_3 : Parameter_3_type;
end record;

type Any_Param_Data (Num_Params : Whatever) is record
   case Num_Params is
   when 1 =>
      Parameter_1 : Param_1_Data;
   when 2 =>
      Parameter_2 : Param_2_Data;
   when 3 =>
      Parameter_3 : Param_3_Data;
   end case;
end record;

Run-time dispatching is also easily implemented using this approach, and
is left as an exercise for the reader.

-- 
Jeff Carter
"I wave my private parts at your aunties."
Monty Python & the Holy Grail



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28  6:53 Robert C. Leif
                   ` (2 preceding siblings ...)
  2002-08-28 17:15 ` Hyman Rosen
@ 2002-08-28 20:27 ` Björn Lundin
  3 siblings, 0 replies; 33+ messages in thread
From: Björn Lundin @ 2002-08-28 20:27 UTC (permalink / raw)


<cut>

> The variant record approach possibly
> would have worked in Pascal; however, it did not compile in the
> cost-free GNAT compiler.
> ---------------------------------------------------
> --Variant Record Approach
> --Does not work
>    type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters :
> Num_Parameters_Type) is --range 1..2
>    record
>       case Num_Parameters  is
>          when 1 =>
>             Parameter_1: Parameter_1_Type;
>          when 2 =>
>             Parameter_1: Parameter_1_Type;
>  --Parameter_1 conflicts with declaration 2 lines above.
>             --Can not have the same signature as the one above.
>             Parameter_2: Parameter_2_Type;
>       end case;
>    end record;
> 
</cut>

this compiles under gnat 3.13p under Linux

/Bj�rn


procedure tst_34 is

   type Num_Parameters_Type is range 1..2;
   type Parameter_1_Type is range 1..56;
   type Parameter_2_Type is range 1..52;


   type Parameter_Rec_Psuedo_Tagged_Type (Num_Parameters : 
Num_Parameters_Type) is --range 1..2
   record
      Parameter_1: Parameter_1_Type;

      case Num_Parameters  is
         when 2 =>
            Parameter_2: Parameter_2_Type;
         when others => null;
      end case;
   end record;


   the_test_1 : Parameter_Rec_Psuedo_Tagged_Type (1);
   the_test_2 : Parameter_Rec_Psuedo_Tagged_Type (2);

begin
  null;
end tst_34;





^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: Run-Time Type Assignment
       [not found] ` <3D6CB4F5.F4E05D76@myob.com>
  2002-08-28 11:37   ` sk
  2002-08-28 15:39   ` Robert C. Leif
@ 2002-08-28 20:54   ` Robert C. Leif
  2002-08-28 22:55     ` Robert A Duff
  2 siblings, 1 reply; 33+ messages in thread
From: Robert C. Leif @ 2002-08-28 20:54 UTC (permalink / raw)


From: Bob Leif
From: Bob Leif
To: Fellow Readers of Comp.Lang.Ada
Firstly, thanks to all who suggested implementations. I now have a
solution based on the Example from Norman Cohen's Ada as a second
language page 377.
The two pages and main procedure below compile. Unfortunately, type
Para_Rec_Psuedo_Tagged_Type is brute force approach. Does anyone have a
simpler implementation?
------------------------------------------------------
package Parameter_Recs_Pkg is
   subtype Para_1_Type is Positive range 1..64_000;
   subtype Para_2_Type is Positive range 1..256;
   subtype Para_3_Type is Positive range 1..1024;
   subtype Para_4_Type is Positive range 1..2048;
   subtype Para_5_Type is Positive range 1..4096;

   subtype Num_Paras_Type is Positive range 1..5;
   Num_Paras : Num_Paras_Type := 1;  

   type Para_Rec_Psuedo_Tagged_Type (Num_Paras :Num_Paras_Type) is
   record
      Para_1  : Para_1_Type; --Always has one parameter
      case Num_Paras  is
         when 1 =>
            null;
         when 2|3|4|5 =>
            Para_2  : Para_2_Type;
            case Num_Paras  is
               when 1|2 =>
                  null;
               when 3|4|5 =>
                  Para_3  : Para_3_Type;
                  case Num_Paras  is
                     when 1|2|3 =>
                        null;
                     when 4|5 =>
                        Para_4  : Para_4_Type;
                        case Num_Paras  is
                           when 1|2|3|4 =>
                              null;
                           when  5 =>
                              Para_5: Para_5_Type;
                        end case;
                  end case;
            end case;
      end case;
   end record;
end Parameter_Recs_Pkg;
------------------------------------------------------------------------
----
------------------------------------------------------------------------
----
generic
   Length : Positive;  
   type Record_Type is private; 
package Array_Of_Records_G_Pkg is
   type Array_Of_Records_Type is array (1 .. Length) of Record_Type; 
   ------------------------------------------------------------
   --Sets the value of an individual record in the array
   procedure Set_Record (
         Array_Of_Records : in out Array_Of_Records_Type; 
         Index            : in     Positive;              
         Record_Var       : in     Record_Type            ); 
   ------------------------------------------------------------
   --Retrieves a record from the array.
   function Get_Record (
         Array_Of_Records : in     Array_Of_Records_Type; 
         Index            : in     Positive               ) 
     return Record_Type; 
   ------------------------------------------------------------
end Array_Of_Records_G_Pkg;
------------------------------------------------------------------------
----
------------------------------------------------------------------------
----
with Parameter_Recs_Pkg;
with Array_Of_Records_G_Pkg;
procedure Test is 
   ---------Table of Contents----------
   subtype Num_Paras_Type is Parameter_Recs_Pkg.Num_Paras_Type;
   subtype Para_Rec_Psuedo_Tagged_Type is
Parameter_Recs_Pkg.Para_Rec_Psuedo_Tagged_Type;
   --------End Table of Contents----------
   Num_Of_Records : Positive       := 5;  
   Num_Paras      : Num_Paras_Type := 2;  
   type Array_Record_Type is new Para_Rec_Psuedo_Tagged_Type 
         (Num_Paras); 
   ---------------------------------------------------
   package Array_Of_Records_Pkg is new Array_Of_Records_G_Pkg(
      Length      => Num_Of_Records,   
      Record_Type => Array_Record_Type);
   ---------------------------------------------------
begin --Test
   null;
end Test;




^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 14:59         ` Lutz Donnerhacke
@ 2002-08-28 22:32           ` Robert A Duff
  2002-08-29 22:55           ` Dmitry A.Kazakov
  1 sibling, 0 replies; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 22:32 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

> * Robert A Duff wrote:
> >In Pascal, downward closures are very useful for making iterators and
> >other user-defined control structures.
> 
> In Ada you use generics for this.

Sometimes, you do.  The syntax is horrible.  Furthermore, generics are
more restrictive -- there are things you can't do, which you could do
with downward closures.

Not to mention the fact that the generic solution requires massive
recompilation of the whole world.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 16:06 ` Run-Time Type Assignment sk
@ 2002-08-28 22:44   ` tmoran
  2002-08-29  0:37   ` tmoran
  1 sibling, 0 replies; 33+ messages in thread
From: tmoran @ 2002-08-28 22:44 UTC (permalink / raw)


 >   type Level_One is new Base_Type with record
 >...
 >   type Level_Two is new Level_One with record
 >...
 >   type Level_Three is new Level_Two with record
   Seems the most straightforward to me.

 But in <mailman.1030517642.16877.comp.lang.ada@ada.eu.org> Bob Leif said:
 > I do not know how to select a subtype of a class at run-time.
     function Read_Whatever return Base_Type'class is
     begin
       -- read and find out what kind of record you have, then return it
       if figured_out_its_Level_One then
         declare
           Result : Level_One;
         begin
           -- fill Result with info
           return Result;
         end;
       elsif figured_out_its_Level_Two then
         declare
           Result : Level_Two;
         begin
           -- fill Result with info
           return Result;
         end;
       ...
     end Read_Whatever;

     One way to handle the different subtypes is

     procedure Process is
       Data : Base_Type'class := Read_Whatever;
     begin
       -- process the Level_One info that's always present
       if Data in Level_One then return;end if; -- that's all in this case
       -- now process the Level_Two stuff that's present in this case
       if Data in Level_Two then return;end if; -- that's all
       -- now process the Level_Three stuff that must be present in this case
       ...

     or, more in OO style:

     procedure Process(Data : in Level_One) is ...
     procedure Process(Data : in Level_Two) is ...
     procedure Process(Data : in Level_Three) is ...

     and then

     declare
       Data : Base_Type'class := Read_Whatever;
     begin
       Process(Base_Type'class(Data));  -- call the appropriate Process routine
     end;

     Since these things are different sizes, you can't put them in an
 array, all of whose elements must be the same size.  But you can put
 in access values.
     type Base_Type_Access is access Base_Type'class;
     Everything : array(1 .. 1_000_000) of Base_Type_Access;
     Count : Natural := 0;

     while not EOF loop
       Count := Count+1;
       Everything(Count) := new Base_Type'class'(Read_Whatever);
     end loop;
     -- Now Everything(1 .. Count) contains pointers to the records.
     -- The records are stored on the heap, each taking only as
     -- much room as it needs.
     for i in 1 .. Count loop                       -- for each record,
       Process(Base_Type'class(Everything(i).all)); -- do appropriate Process
     end loop;
 ---
 Code not tested!



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 18:03         ` Frank J. Lhota
  2002-08-28 18:37           ` Pat Rogers
@ 2002-08-28 22:47           ` Robert A Duff
  2002-08-29 13:32             ` Ben Brosgol
  1 sibling, 1 reply; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 22:47 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> writes:

> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> news:wccn0r7hx5y.fsf@shell01.TheWorld.com...
> > Kilgallen@SpamCop.net (Larry Kilgallen) writes:
> >
> > > What is a downward closure ?
> >
> > The ability to pass a procedure as a parameter to a procedure.
> 
> <snip>
> 
> > GNAT supports downward closures via the 'Unrestricted_Access attribute,
> > but that's not Ada (unfortunately).
> 
> What about using just the plain old 'Access attribute to pass a pointer to
> the procedure as a parameter? That is supported by all Ada 95 compilers.

No, 'Access doesn't work.  Typically, the loop body (the procedure to be
passed as a parameter) is more nested than the iterator, which makes
'Access illegal.

function Count_Items(X: Container) return Natural is
    Result: Natural := 0;
    
    procedure Incr(...) is
    begin
        Result := Result + 1;
    end Incr;
begin
    Iterate(X, Incr'Access); -- Wrong!
    return Result;
end Count_Items;

That's illegal, because Incr is more nested than the access-to-procedure
type passed to the iterator (which is defined in some package
elsewhere).

Usually, the loop body (e.g. Incr) needs to be more nested so it can see
some local variables.

GNAT's 'Unrestricted_Access attribute works in this case, but it is
nonportable and dangerous.  The question was whether Pascal supports
features not supported by Ada: in this case, it does; the feature is
portable and safe (compared to 'Unrestricted_Access).  It's more
readable, too, since you can just pass the procedure, not a pointer to
it.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 20:54   ` Robert C. Leif
@ 2002-08-28 22:55     ` Robert A Duff
  2002-08-29  3:18       ` Robert C. Leif
  0 siblings, 1 reply; 33+ messages in thread
From: Robert A Duff @ 2002-08-28 22:55 UTC (permalink / raw)


"Robert C. Leif" <rleif@rleif.com> writes:

> From: Bob Leif
> From: Bob Leif
> To: Fellow Readers of Comp.Lang.Ada
> Firstly, thanks to all who suggested implementations. I now have a
> solution based on the Example from Norman Cohen's Ada as a second
> language page 377.
> The two pages and main procedure below compile. Unfortunately, type
> Para_Rec_Psuedo_Tagged_Type is brute force approach. Does anyone have a
> simpler implementation?

In this case, all the "Para"'s are of type Positive, so you could make
an array inside the record, bounds 1..Num_Paras.  You lose some range
checking, unfortunately.  If the types were not all the same type, then
*make* them be all of the same type by the usual methods (pointer to
class-wide, pointer to variant record, etc).

> ------------------------------------------------------
> package Parameter_Recs_Pkg is
>    subtype Para_1_Type is Positive range 1..64_000;
>    subtype Para_2_Type is Positive range 1..256;
>    subtype Para_3_Type is Positive range 1..1024;
>    subtype Para_4_Type is Positive range 1..2048;
>    subtype Para_5_Type is Positive range 1..4096;
> 
>    subtype Num_Paras_Type is Positive range 1..5;
>    Num_Paras : Num_Paras_Type := 1;  
> 
>    type Para_Rec_Psuedo_Tagged_Type (Num_Paras :Num_Paras_Type) is
>    record
>       Para_1  : Para_1_Type; --Always has one parameter
>       case Num_Paras  is
>          when 1 =>
>             null;
>          when 2|3|4|5 =>
>             Para_2  : Para_2_Type;
>             case Num_Paras  is
>                when 1|2 =>
>                   null;
>                when 3|4|5 =>
>                   Para_3  : Para_3_Type;
>                   case Num_Paras  is
>                      when 1|2|3 =>
>                         null;
>                      when 4|5 =>
>                         Para_4  : Para_4_Type;
>                         case Num_Paras  is
>                            when 1|2|3|4 =>
>                               null;
>                            when  5 =>
>                               Para_5: Para_5_Type;
>                         end case;
>                   end case;
>             end case;
>       end case;
>    end record;
> end Parameter_Recs_Pkg;

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 16:06 ` Run-Time Type Assignment sk
  2002-08-28 22:44   ` tmoran
@ 2002-08-29  0:37   ` tmoran
  1 sibling, 0 replies; 33+ messages in thread
From: tmoran @ 2002-08-29  0:37 UTC (permalink / raw)


>   type Level_One is new Base_Type with record
>...
>   type Level_Two is new Level_One with record
>...
>   type Level_Three is new Level_Two with record
  Seems the most straightforward to me.

But in <mailman.1030517642.16877.comp.lang.ada@ada.eu.org> Bob Leif said:
> I do not know how to select a subtype of a class at run-time.
    function Read_Whatever return Base_Type'class is
    begin
      -- read and find out what kind of record you have, then return it
      if figured_out_its_Level_One then
        declare
          Result : Level_One;
        begin
          -- fill Result with info
          return Result;
        end;
      elsif figured_out_its_Level_Two then
        declare
          Result : Level_Two;
        begin
          -- fill Result with info
          return Result;
        end;
      ...
    end Read_Whatever;

    One way to handle the different subtypes is

    procedure Process is
      Data : Base_Type'class := Read_Whatever;
    begin
      -- process the Level_One info that's always present
      if Data in Level_One then return;end if; -- that's all in this case
      -- now process the Level_Two stuff that's present in this case
      if Data in Level_Two then return;end if; -- that's all
      -- now process the Level_Three stuff that must be present in this case
      ...

    or, more in OO style:

    procedure Process(Data : in Level_One) is ...
    procedure Process(Data : in Level_Two) is ...
    procedure Process(Data : in Level_Three) is ...

    and then

    declare
      Data : Base_Type'class := Read_Whatever;
    begin
      Process(Base_Type'class(Data));  -- call the appropriate Process routine
    end;

    Since these things are different sizes, you can't put them in an
array, all of whose elements must be the same size.  But you can put
in access values.
    type Base_Type_Access is access Base_Type'class;
    Everything : array(1 .. 1_000_000) of Base_Type_Access;
    Count : Natural := 0;

    while not EOF loop
      Count := Count+1;
      Everything(Count) := new Base_Type'class'(Read_Whatever);
    end loop;
    -- Now Everything(1 .. Count) contains pointers to the records.
    -- The records are stored on the heap, each taking only as
    -- much room as it needs.
    for i in 1 .. Count loop                       -- for each record,
      Process(Base_Type'class(Everything(i).all)); -- do appropriate Process
    end loop;
---
Code not tested!



^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: Run-Time Type Assignment
  2002-08-28 22:55     ` Robert A Duff
@ 2002-08-29  3:18       ` Robert C. Leif
  0 siblings, 0 replies; 33+ messages in thread
From: Robert C. Leif @ 2002-08-29  3:18 UTC (permalink / raw)


From: Bob Leif
To: Robert A Duff et al. 
I was being lazy. The actual parameters include unsigned 8, 16, and 32
bit integers; floats, one and two dimensional arrays, and possibly
booleans. Fortunately, the array consists of one type of record, which
can have 1 to approximately 15 fields (elements). The data type
possibilities and number of elements in a record will increase as the
technology advances.  

-----Original Message-----
From: comp.lang.ada-admin@ada.eu.org
[mailto:comp.lang.ada-admin@ada.eu.org] On Behalf Of Robert A Duff
Sent: Wednesday, August 28, 2002 3:55 PM
To: comp.lang.ada@ada.eu.org
Subject: Re: Run-Time Type Assignment

"Robert C. Leif" <rleif@rleif.com> writes:

> From: Bob Leif
> From: Bob Leif
> To: Fellow Readers of Comp.Lang.Ada
> Firstly, thanks to all who suggested implementations. I now have a
> solution based on the Example from Norman Cohen's Ada as a second
> language page 377.
> The two pages and main procedure below compile. Unfortunately, type
> Para_Rec_Psuedo_Tagged_Type is brute force approach. Does anyone have
a
> simpler implementation?

In this case, all the "Para"'s are of type Positive, so you could make
an array inside the record, bounds 1..Num_Paras.  You lose some range
checking, unfortunately.  If the types were not all the same type, then
*make* them be all of the same type by the usual methods (pointer to
class-wide, pointer to variant record, etc).
SNIP including end.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 22:47           ` Robert A Duff
@ 2002-08-29 13:32             ` Ben Brosgol
  2002-08-29 13:52               ` SIMON Claude
                                 ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Ben Brosgol @ 2002-08-29 13:32 UTC (permalink / raw)


Bob Duff wrote:

> > > GNAT supports downward closures via the 'Unrestricted_Access
attribute,
> > > but that's not Ada (unfortunately).
> >
> > What about using just the plain old 'Access attribute to pass a pointer
to
> > the procedure as a parameter? That is supported by all Ada 95 compilers.
>
> No, 'Access doesn't work.  Typically, the loop body (the procedure to be
> passed as a parameter) is more nested than the iterator, which makes
> 'Access illegal.
 ... snip ...
> GNAT's 'Unrestricted_Access attribute works in this case, but it is
> nonportable and dangerous.  The question was whether Pascal supports
> features not supported by Ada: in this case, it does; the feature is
> portable and safe (compared to 'Unrestricted_Access).

The reason it is safe to pass nested subprograms as parameters in Pascal is
that Pascal does not allow subprograms to be used as values for variables or
placed in data structures.  GNAT's 'Unrestricted_Access is just as safe,
provided that you abide by the Pascal restrictions.  (I.e.,
Unrestricted_Access still entails the other checks required by the language;
e.g. static subtype conformance for corresponding formals, matching
conventions.)  For example:

procedure Test_Unrestricted_Access is
  type Acc is access procedure;
  Ref : Acc;
  procedure P1(N : Integer) is begin null; end P1;
  procedure P2;
  pragma Convention(C, P2);
  procedure P2 is begin null; end P2;
begin
  Ref := P1'Unrestricted_Access; -- error
  Ref := P2'Unrestricted_Access; -- error
  declare
    procedure Q is begin null; end Q;
  begin
    Ref := Q'Unrestricted_Access; -- OK
    Ref := Q'Access;  --error
  end;
end Test_Unrestricted_Access;

The lines indicated by the "-- error" comments were diagnosed as
compile-time errors by GNAT.

As for portability, if you are using GNAT why would you ever want to move to
some other compiler? :-)

Ben Brosgol
Ada Core Technologies






^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 13:32             ` Ben Brosgol
@ 2002-08-29 13:52               ` SIMON Claude
  2002-08-29 14:30                 ` Robert A Duff
  2002-08-29 14:56               ` Robert A Duff
  2002-08-29 15:09               ` Larry Kilgallen
  2 siblings, 1 reply; 33+ messages in thread
From: SIMON Claude @ 2002-08-29 13:52 UTC (permalink / raw)


Does a "limited access procedure" could be THE solution ?

Claude Simon

Ben Brosgol wrote:
> 
> Bob Duff wrote:
> 
> > > > GNAT supports downward closures via the 'Unrestricted_Access
> attribute,
> > > > but that's not Ada (unfortunately).
> > >
> > > What about using just the plain old 'Access attribute to pass a pointer
> to
> > > the procedure as a parameter? That is supported by all Ada 95 compilers.
> >
> > No, 'Access doesn't work.  Typically, the loop body (the procedure to be
> > passed as a parameter) is more nested than the iterator, which makes
> > 'Access illegal.
>  ... snip ...
> > GNAT's 'Unrestricted_Access attribute works in this case, but it is
> > nonportable and dangerous.  The question was whether Pascal supports
> > features not supported by Ada: in this case, it does; the feature is
> > portable and safe (compared to 'Unrestricted_Access).
> 
> The reason it is safe to pass nested subprograms as parameters in Pascal is
> that Pascal does not allow subprograms to be used as values for variables or
> placed in data structures.  GNAT's 'Unrestricted_Access is just as safe,
> provided that you abide by the Pascal restrictions.  (I.e.,
> Unrestricted_Access still entails the other checks required by the language;
> e.g. static subtype conformance for corresponding formals, matching
> conventions.)  For example:
> 
> procedure Test_Unrestricted_Access is
>   type Acc is access procedure;
>   Ref : Acc;
>   procedure P1(N : Integer) is begin null; end P1;
>   procedure P2;
>   pragma Convention(C, P2);
>   procedure P2 is begin null; end P2;
> begin
>   Ref := P1'Unrestricted_Access; -- error
>   Ref := P2'Unrestricted_Access; -- error
>   declare
>     procedure Q is begin null; end Q;
>   begin
>     Ref := Q'Unrestricted_Access; -- OK
>     Ref := Q'Access;  --error
>   end;
> end Test_Unrestricted_Access;
> 
> The lines indicated by the "-- error" comments were diagnosed as
> compile-time errors by GNAT.
> 
> As for portability, if you are using GNAT why would you ever want to move to
> some other compiler? :-)
> 
> Ben Brosgol
> Ada Core Technologies



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 15:09               ` Larry Kilgallen
@ 2002-08-29 14:29                 ` Marin D. Condic
  0 siblings, 0 replies; 33+ messages in thread
From: Marin D. Condic @ 2002-08-29 14:29 UTC (permalink / raw)


"Larry Kilgallen" <Kilgallen@SpamCop.net> wrote in message
news:RVbCqwNhXY7R@eisner.encompasserve.org...
> In article <H1LxwL.45o@world.std.com>, "Ben Brosgol"
<brosgol@world.std.com> writes:
>
> > As for portability, if you are using GNAT why would you ever want to
move to
> > some other compiler? :-)
>
> Changing platforms to one not supported by GNAT.

Or wanting to distribute source that is portable no matter who's compiler
someone wants to take it to - utility code, for example. (Claw, Booch,
Grace, etc.)

Gnat is a fine compiler, but it isn't the only one. ;-)

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com

Enabling Digital.
Our Vision is to be the biggest supplier worldwide of digital gateway
technology.
www.pacemicro.com





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 13:52               ` SIMON Claude
@ 2002-08-29 14:30                 ` Robert A Duff
  2002-08-29 18:27                   ` Randy Brukardt
  0 siblings, 1 reply; 33+ messages in thread
From: Robert A Duff @ 2002-08-29 14:30 UTC (permalink / raw)


SIMON Claude <claude.simon@equipement.gouv.fr> writes:

> Does a "limited access procedure" could be THE solution ?

Yes.  Two solutions were proposed during the Ada 9X design.
That was one of them.  I think the other involved some sort
of run-time accessibility-level checking (like access parameters).

Neither feature made it into the language.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 13:32             ` Ben Brosgol
  2002-08-29 13:52               ` SIMON Claude
@ 2002-08-29 14:56               ` Robert A Duff
  2002-08-30  3:04                 ` Ben Brosgol
  2002-08-29 15:09               ` Larry Kilgallen
  2 siblings, 1 reply; 33+ messages in thread
From: Robert A Duff @ 2002-08-29 14:56 UTC (permalink / raw)


"Ben Brosgol" <brosgol@world.std.com> writes:

> The reason it is safe to pass nested subprograms as parameters in Pascal is
> that Pascal does not allow subprograms to be used as values for variables or
> placed in data structures.  GNAT's 'Unrestricted_Access is just as safe,
> provided that you abide by the Pascal restrictions.

Yeah, and array indexing in C is just as safe as in Ada -- so long as
you don't index outside the array bounds.  Driving 120 miles per hour
in a 30 mph zone without wearing a seat belt is perfectly safe -- so
long as you don't cause a collision.

OK, sorry for infamatory rhetoric, Ben, but claiming that
'Unrestricted_Access is as safe as in Pascal is just plain silly.
The fact is, you can accidentally create dangling pointers using
'Unrestricted_Access, which you can't do by passing procedural
parameters in Pascal.

>...(I.e.,
> Unrestricted_Access still entails the other checks required by the language;
> e.g. static subtype conformance for corresponding formals, matching
> conventions.)  For example:
> 
> procedure Test_Unrestricted_Access is
>   type Acc is access procedure;
>   Ref : Acc;
>   procedure P1(N : Integer) is begin null; end P1;
>   procedure P2;
>   pragma Convention(C, P2);
>   procedure P2 is begin null; end P2;
> begin
>   Ref := P1'Unrestricted_Access; -- error
>   Ref := P2'Unrestricted_Access; -- error

Well, it's nice that it detects *some* errors (it detects misspellings
like 'Unrestricted_Acess, too!), but it doesn't detect dangling
pointers.

>   declare
>     procedure Q is begin null; end Q;
>   begin
>     Ref := Q'Unrestricted_Access; -- OK

That's the problem (the above "OK").  If you call Ref.all later, you're
in trouble.  GNAT thinks it's OK, but it is *not* OK.

>     Ref := Q'Access;  --error
>   end;
> end Test_Unrestricted_Access;
> 
> The lines indicated by the "-- error" comments were diagnosed as
> compile-time errors by GNAT.
> 
> As for portability, if you are using GNAT why would you ever want to move to
> some other compiler? :-)

I see the smiley, but, for example, the company I work for (SofCheck,
Inc.) produces Ada compilers for targets that GNAT does not support.
And we've recently heard Robert Dewar pointing out that ACT is not
attempting to cover the *entire* Ada business -- quite reasonably, ACT
has a narrower focus, as do other vendors.

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 13:32             ` Ben Brosgol
  2002-08-29 13:52               ` SIMON Claude
  2002-08-29 14:56               ` Robert A Duff
@ 2002-08-29 15:09               ` Larry Kilgallen
  2002-08-29 14:29                 ` Marin D. Condic
  2 siblings, 1 reply; 33+ messages in thread
From: Larry Kilgallen @ 2002-08-29 15:09 UTC (permalink / raw)


In article <H1LxwL.45o@world.std.com>, "Ben Brosgol" <brosgol@world.std.com> writes:

> As for portability, if you are using GNAT why would you ever want to move to
> some other compiler? :-)

Changing platforms to one not supported by GNAT.



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 14:30                 ` Robert A Duff
@ 2002-08-29 18:27                   ` Randy Brukardt
  0 siblings, 0 replies; 33+ messages in thread
From: Randy Brukardt @ 2002-08-29 18:27 UTC (permalink / raw)


The ARG has looks at solutions to this problem for the upcoming
Amendment. The current proposal can be found in AI-254
(http://www.ada-auth.org/AI-SUMMARY.HTML is the AI index). Be aware
though that there is a substantial concern that this solution is too
complex for the problem.

(GNAT's solution only works because of the details of their
implementation. In general, you need a "fatter" than normal subprogram
access type in order to carry the additional information necessary to
make these calls and have them work. So the 'simple' solution of
adopting 'Unrestricted_Access can't be used.)

                  Randy Brukardt.


Robert A Duff wrote in message ...
>SIMON Claude <claude.simon@equipement.gouv.fr> writes:
>
>> Does a "limited access procedure" could be THE solution ?
>
>Yes.  Two solutions were proposed during the Ada 9X design.
>That was one of them.  I think the other involved some sort
>of run-time accessibility-level checking (like access parameters).
>
>Neither feature made it into the language.
>
>- Bob





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-28 14:59         ` Lutz Donnerhacke
  2002-08-28 22:32           ` Robert A Duff
@ 2002-08-29 22:55           ` Dmitry A.Kazakov
  1 sibling, 0 replies; 33+ messages in thread
From: Dmitry A.Kazakov @ 2002-08-29 22:55 UTC (permalink / raw)


Lutz Donnerhacke wrote:

> * Robert A Duff wrote:
>>Kilgallen@SpamCop.net (Larry Kilgallen) writes:
>>> What is a downward closure ?
>>
>>The ability to pass a procedure as a parameter to a procedure.
>>The "downward" means the closure is passed "down" from caller to
>>callee.  This is more restrictive than the "full closures" which are
>>found in Lisp and many other languages of that ilk; a full closure may
>>be *returned* from a procedure, and may be assigned into a variable.
>>
>>GNAT supports downward closures via the 'Unrestricted_Access attribute,
>>but that's not Ada (unfortunately).
>>
>>In Pascal, downward closures are very useful for making iterators and
>>other user-defined control structures.
> 
> In Ada you use generics for this.

It is a nasty work-around. IMO Ada should have true subroutine types 
[restricted of course].

-- 
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-29 14:56               ` Robert A Duff
@ 2002-08-30  3:04                 ` Ben Brosgol
  2002-08-30 22:54                   ` Robert A Duff
  0 siblings, 1 reply; 33+ messages in thread
From: Ben Brosgol @ 2002-08-30  3:04 UTC (permalink / raw)


> > The reason it is safe to pass nested subprograms as parameters in Pascal
is
> > that Pascal does not allow subprograms to be used as values for
variables or
> > placed in data structures.  GNAT's 'Unrestricted_Access is just as safe,
> > provided that you abide by the Pascal restrictions.
>
> Yeah, and array indexing in C is just as safe as in Ada -- so long as
> you don't index outside the array bounds.  Driving 120 miles per hour
> in a 30 mph zone without wearing a seat belt is perfectly safe -- so
> long as you don't cause a collision.
>
> OK, sorry for infamatory rhetoric, Ben, but claiming that
> 'Unrestricted_Access is as safe as in Pascal is just plain silly.
> The fact is, you can accidentally create dangling pointers using
> 'Unrestricted_Access, which you can't do by passing procedural
> parameters in Pascal.

Hmm, I try not to say too many silly things (unless I flag them with
smileys) so I guess I need to give some additional explanation for my
comment.

First, I was not claiming that 'Unrestricted_Access is a completely safe
construct.  Obviously you can create dangling references.

But lots of programs have no need for the generality of stuffing a (pointer
to a) subprogram in a data structure, or assigning it to a variable; they
only need to pass subprograms as run-time parameters.  For such programs it
will be perfectly safe to use 'Unrestricted_Access to pass a nested
subprogram as a parameter; there is no danger of dangling references, and
you still get the other checks that 'Access entails.  (Phrased differently:
the context of the original discussion was whether anything that could be
done in Pascal could be done in Ada.  So if you have a Pascal program that
passes a procedure or function as a parameter, and then convert the program
to Ada, there is no lack of safety in using Unrestricted_Access.)  I see
this as different from the array indexing case.  It is hard, if all you want
to do is pass a subprogram as a parameter, to accidentally store it into a
data structure.  It is easy to make a programming error and accidentally
have an array index out of bounds.

> >...(I.e.,
> > Unrestricted_Access still entails the other checks required by the
language;
> > e.g. static subtype conformance for corresponding formals, matching
> > conventions.)  For example:

> Well, it's nice that it detects *some* errors (it detects misspellings
> like 'Unrestricted_Acess, too!), but it doesn't detect dangling
> pointers.

It's not clear when to do the detection (see below).

> >   declare
> >     procedure Q is begin null; end Q;
> >   begin
> >     Ref := Q'Unrestricted_Access; -- OK
>
> That's the problem (the above "OK").  If you call Ref.all later, you're
> in trouble.  GNAT thinks it's OK, but it is *not* OK.

Might or might not be OK; depends on your definition of "later".  You're OK
if the call is only from the block that declares Q.  (And you're probably
still OK even if the call is from an outer scope, if (as is the case here) Q
does not make any up-level references to stack variables.)

But the point is not that Unrestricted_Access can lead to dangling
references.  It's that you still get the checks as for 'Access except for
scope accessibility, and that you don't need that check if you are only
passing a subprogram as a parameter and not assigning it to a variable.

-Ben







^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: Run-Time Type Assignment
  2002-08-30  3:04                 ` Ben Brosgol
@ 2002-08-30 22:54                   ` Robert A Duff
  0 siblings, 0 replies; 33+ messages in thread
From: Robert A Duff @ 2002-08-30 22:54 UTC (permalink / raw)


"Ben Brosgol" <brosgol@world.std.com> writes:

> Hmm, I try not to say too many silly things (unless I flag them with
> smileys) so I guess I need to give some additional explanation for my
> comment.

OK, Ben, I apologize for the "silly" accusation.  I shouldn't use such
inflamatory rhetoric.

But I stand by my claims: 'Unrestricted_Access is not safe, and not portable.

> First, I was not claiming that 'Unrestricted_Access is a completely safe
> construct.  Obviously you can create dangling references.

Which is why I said 'Unrestricted_Access is "unsafe".

> But lots of programs have no need for the generality of stuffing a (pointer
> to a) subprogram in a data structure, or assigning it to a variable; they
> only need to pass subprograms as run-time parameters.  For such programs it
> will be perfectly safe to use 'Unrestricted_Access to pass a nested
> subprogram as a parameter; there is no danger of dangling references, and
> you still get the other checks that 'Access entails.  (Phrased differently:
> the context of the original discussion was whether anything that could be
> done in Pascal could be done in Ada.  So if you have a Pascal program that
> passes a procedure or function as a parameter, and then convert the program
> to Ada, there is no lack of safety in using Unrestricted_Access.)

Well, that's not Ada, that's GNAT Ada, but still...

>...  I see
> this as different from the array indexing case.  It is hard, if all you want
> to do is pass a subprogram as a parameter, to accidentally store it into a
> data structure.

True.  However, it is perfectly reasonable to save procedure pointers
into globals -- that's what the Ada 95 features of access-to-procedure
and P'Access are for.  So suppose we have a procedure:

    type Proc is access procedure;
    procedure Mumble(X: Proc);

I'm not going to show you the body of Mumble, because that would be
cheating.  Now is it OK to pass Nested_Proc'Unrestricted_Access
to Mumble?  There's no way to tell.  (Well, you can look at the
comments, but you can't claim that as language support.)

>...  It is easy to make a programming error and accidentally
> have an array index out of bounds.
> 
> > >...(I.e.,
> > > Unrestricted_Access still entails the other checks required by the
> language;
> > > e.g. static subtype conformance for corresponding formals, matching
> > > conventions.)  For example:
> 
> > Well, it's nice that it detects *some* errors (it detects misspellings
> > like 'Unrestricted_Acess, too!), but it doesn't detect dangling
> > pointers.
> 
> It's not clear when to do the detection (see below).

It's quite clear to me.  We need a new kind of access-to-procedure type,
a "limited" one that doesn't allow assignment.  Then passing nested
procedures to the limited type is OK, and assignment is illegal (that
is, the detection happens when you try to assign (or return, etc)).
At least, that's *one* safe design.  There are others.

> > >   declare
> > >     procedure Q is begin null; end Q;
> > >   begin
> > >     Ref := Q'Unrestricted_Access; -- OK
> >
> > That's the problem (the above "OK").  If you call Ref.all later, you're
> > in trouble.  GNAT thinks it's OK, but it is *not* OK.
> 
> Might or might not be OK; depends on your definition of "later".  You're OK
> if the call is only from the block that declares Q.  (And you're probably
> still OK even if the call is from an outer scope, if (as is the case here) Q
> does not make any up-level references to stack variables.)

By "later", I meant, "after that block is left".

In most real examples, Q *does* make up-level refs -- that's why it is
nested.  Anyway, whether or not Q refers to globals, calling Q when it
no longer exists should be considered an error -- and GNAT does not
detect this error.

> But the point is not that Unrestricted_Access can lead to dangling
> references.

I disagree -- the point (I was trying to make) is exactly that
'Unrestricted_Access is unsafe in that it can cause dangling pointers,
which is not possible for the corresponding feature in Pascal.

The key point to understanding this issue is to see that the Pascal
feature is a different feature from Ada 95's access-to-procedure.
'Unrestricted_Access tries to combine them into one -- there lies the
trouble.

The Pascal feature is to allow procedures to be passed inward,
but not assigned or returned.  That's what I call "downward closures".

The Ada 95 feature is to allow top level procedures to be passed around
and returned and assigned into global variables -- and then called much
later.  That's what I call "callbacks".

Both features are useful; they're not the same feature.
Both can be supported safely.
It's unfortunate, IMHO, that Ada 95 supports only one of them,
and that GNAT supports the other unsafely.

>...It's that you still get the checks as for 'Access except for
> scope accessibility, and that you don't need that check if you are only
> passing a subprogram as a parameter and not assigning it to a variable.

If you pass it as a parameter, it could be assigned to a global
variable.  That's the problem.

> -Ben

- Bob



^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2002-08-30 22:54 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <005101c24ea9$0de9c960$789a0844@robertqgx6k4x9>
2002-08-28 16:06 ` Run-Time Type Assignment sk
2002-08-28 22:44   ` tmoran
2002-08-29  0:37   ` tmoran
     [not found] <002a01c24e5f$9ee347b0$789a0844@robertqgx6k4x9>
2002-08-28 11:33 ` sk
     [not found] ` <3D6CB4F5.F4E05D76@myob.com>
2002-08-28 11:37   ` sk
2002-08-28 15:39   ` Robert C. Leif
2002-08-28 18:53     ` Jeffrey Carter
2002-08-28 20:54   ` Robert C. Leif
2002-08-28 22:55     ` Robert A Duff
2002-08-29  3:18       ` Robert C. Leif
2002-08-28  6:53 Robert C. Leif
2002-08-28 11:04 ` Robert Dewar
2002-08-28 13:35   ` Robert A Duff
2002-08-28 14:56     ` Larry Kilgallen
2002-08-28 14:31       ` Robert A Duff
2002-08-28 14:59         ` Lutz Donnerhacke
2002-08-28 22:32           ` Robert A Duff
2002-08-29 22:55           ` Dmitry A.Kazakov
2002-08-28 18:03         ` Frank J. Lhota
2002-08-28 18:37           ` Pat Rogers
2002-08-28 22:47           ` Robert A Duff
2002-08-29 13:32             ` Ben Brosgol
2002-08-29 13:52               ` SIMON Claude
2002-08-29 14:30                 ` Robert A Duff
2002-08-29 18:27                   ` Randy Brukardt
2002-08-29 14:56               ` Robert A Duff
2002-08-30  3:04                 ` Ben Brosgol
2002-08-30 22:54                   ` Robert A Duff
2002-08-29 15:09               ` Larry Kilgallen
2002-08-29 14:29                 ` Marin D. Condic
2002-08-28 13:41 ` Robert A Duff
2002-08-28 17:15 ` Hyman Rosen
2002-08-28 20:27 ` Björn Lundin

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