[comp.lang.ada] limited private types, "=" operator

erickson@cs.nps.navy.mil (David Erickson) (08/02/90)

Is there any way to define "=" for a limited private type which is an
access type (which may be null)?  The problem arises trying to test for
null without producing an infinitely recursive definition.

The only solution that I am aware of is to use UNCHECKED_CONVERSION to
retype the access type during the test for null, but this is a hack.
Is there a cleaner solution?

Thanks -

	Dave Erickson

mackey@scs.fiu.edu (08/02/90)

In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:
>Is there any way to define "=" for a limited private type which is an
>access type (which may be null)?  The problem arises trying to test for
>null without producing an infinitely recursive definition.
>
>The only solution that I am aware of is to use UNCHECKED_CONVERSION to
>retype the access type during the test for null, but this is a hack.
>Is there a cleaner solution?
>
>Thanks -
>
>	Dave Erickson

The easiest way to solve this problem is not to say
    type blurg is limited private
    ...
    type blurg is access widget;
at all.  Instead, say:
    type blurg is limited private
    ...
    type blurg_pointer is access widget;
    type blurg is record
            value : blurg_pointer;
         end record;

Then, when you want to deal with the procedure call "=" which
compares blurgs, you use the record.  Inside the body of the package,
you qualify the object with the .value field and you then get the
"=" which compares the pointers themselves.  The client of this
package of course can not get to this function.

.

NCOHEN@IBM.COM ("Norman H. Cohen") (08/02/90)

Ref: INFO-ADA Digest Volume 90 Issue 148 (Wed, Aug 1, 1990) Item #2

David Erickson asks:

 >Is there any way to define "=" for a limited private type which is an
 >access type (which may be null)?  The problem arises trying to test for
 >null without producing an infinitely recursive definition.

You can define an access type in the private part corresponding to the
internal view of the type as a pointer.  The full type declaration
for the limited private type should derive from this type.  The
redefinition of equality in the package spec will apply only to the
derived type, not to the parent.  Thus two views of the same data
structure are available in the package body, one corresponding to a
pointer view and one corresponding to the abstraction for which "=" has
been redefined.  The two views are embodied by two different types,
each with a version of "=" appropriate to that view.  The package body
can convert between the two types, using not Unchecked_Conversion, but
conversion between a derived type and its parent.  For example:

   package Integer_List_Package is
      type Integer_List_Type is limited private;
      function "=" (Left, Right: Integer_List_Type) return Boolean;
      -- [other subprograms]
   private
      -- Ordinary declaration of a recursive access type:
      type List_Cell_Type;
      type Cell_Pointer_Type is access List_Cell_Type;
      type List_Cell_Type is
         record
            Value_Part : Integer;
            Link_Part  : Cell_Pointer_Type;
         end record;
      -- Full declaration of the limited private type:
      type Integer_List_Type is new Cell_Pointer_Type;
   end Integer_List_Package;

   package body Integer_List_Package is
      function "=" (Left, Right: Integer_List_Type) return Boolean is
         Left_Pointer  : Cell_Pointer_Type := Cell_Pointer_Type (Left);
         Right_Pointer : Cell_Pointer_Type := Cell_Pointer_Type (Right);
      begin
         loop
            if Left_Pointer = null then
               return Right_Pointer = null;
            elsif Right_Pointer = null then
               return False;
            else
               Left_Pointer := Left_Pointer.Link_Part;
               Right_Pointer := Right_Pointer.Link_Part;
         end loop;
      end "=";
      -- [other subprograms]
   end Integer_List_Package;

Left_Pointer and Right_Pointer are declared to be of Cell_Pointer_Type
and initialized using type conversions.  The three = operators in the
if statement all have left operands of Cell_Pointer_Type, so they
invoke the predefined access-type equality for Cell_Pointer_Type, not
(recursively) the redefined "=" for Integer_List_Type.

kassover@minerva.crd.ge.com (David Kassover) (08/03/90)

In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:
|Is there any way to define "=" for a limited private type which is an
|access type (which may be null)?  The problem arises trying to test for
|null without producing an infinitely recursive definition.
|
|The only solution that I am aware of is to use UNCHECKED_CONVERSION to
|retype the access type during the test for null, but this is a hack.
|Is there a cleaner solution?
|

Export from the package defining the limited type a function that
returns TRUE if the access type variable is not null.  Or the other way
around, if you prefer.

--
David Kassover             "Proper technique helps protect you against
kassover@ra.crd.ge.com	    sharp weapons and dull judges."
kassover@crd.ge.com			F. Collins

erickson@cs.nps.navy.mil (David Erickson) (08/03/90)

In article <10687@crdgw1.crd.ge.com> kassover@minerva.crd.ge.com (David Kassover) writes:
>In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:
>|Is there any way to define "=" for a limited private type which is an
>|access type (which may be null)?  The problem arises trying to test for
>|null without producing an infinitely recursive definition.
>|
>|The only solution that I am aware of is to use UNCHECKED_CONVERSION to
>|retype the access type during the test for null, but this is a hack.
>|Is there a cleaner solution?
>|
>
>Export from the package defining the limited type a function that
>returns TRUE if the access type variable is not null.  Or the other way
>around, if you prefer.
>
>--
>David Kassover             "Proper technique helps protect you against
>kassover@ra.crd.ge.com	    sharp weapons and dull judges."
>kassover@crd.ge.com			F. Collins


This will not work in this case.  I specifically need to define "="
for a list which is implemented as a linked list.  In this case, "="
should return true if the two lists being compared are the same length
and the contents of each node are equal.  The user should not be aware
that the implementation uses pointers.  The problem is that I cannot
find a way to use the predefined "=" to test for null in the definition
for "=" that I am exporting.  According to the ARM, the predefined "="
is implicitly declared immediately after the type declaration, prior to
the next statement.  However, my declaration of "=" supersedes the
implicit "=", and I can think of no way to capture the implicit "=".

-Dave Erickson



Erickson@cs.nps.navy.mil

sampson@cod.NOSC.MIL (Charles H. Sampson) (08/04/90)

In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:
>Is there any way to define "=" for a limited private type which is an
>access type (which may be null)?  The problem arises trying to test for
>null without producing an infinitely recursive definition.

     This is a special case of the problem of breaking the recursion when
defining an overloaded operator on a private type.  The LRM contains an
example, 7.4.2(13).  In that example, the private type was realized as a
named type (Integer) and the name was used to convert from the private
type to a type different from that of the function's arguments.  In your
case, the realization of your private type has no name, in the straight-
forward implementation, so you have to circle around the problem in order
to give it a name:

   ...
   TYPE Ltd_pvt IS LIMITED PRIVATE;
   ...
PRIVATE
   ...
   TYPE Type_name IS ACCESS List_link;
   TYPE Ltd_pvt IS NEW Type_name;
   ...
END PACKAGE ...;

PACKAGE BODY ...
   ...
   FUNCTION "="(L, R : Ltd_pvt) RETURN Boolean IS

   BEGIN
      ...
      IF Typ_name(L) = NULL THEN ...
      ...
   END "=";

                               Charlie Sampson

clay@titan.tsd.arlut.utexas.edu (Clay Johnson) (08/10/90)

In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:

>   Is there any way to define "=" for a limited private type which is an
>   access type (which may be null)?  The problem arises trying to test for
>   null without producing an infinitely recursive definition.
>
>   The only solution that I am aware of is to use UNCHECKED_CONVERSION to
>   retype the access type during the test for null, but this is a hack.
>   Is there a cleaner solution?

I have not done so, but you should be able to `dereference' the "="
that appears within your overloaded "=" function by using the dotted
notation, prepending the package name STANDARD where you want the
original interpretation.  Of course, you must then use the functional
rather infix notation:

	if STANDARD."="(POINTER,null) then ...

I'm no Ada expert, but it's my understanding that the dot notation may
always be used to avoid ambiguity and, specifically, unintentional
recursion when overloading a subprogram or operator.  In general this
can be useful; depending upon your implementation, you may want both
the original operator and the new operator (recursively) available at
the same time.  For instance, if your new operator is meant to
compare two recursively defined structures, like binary trees, then
you may wish to define the new operator recursively, while also
refering to the original interpretation of the operator.

Let me know if this works,
Clay

erickson@cs.nps.navy.mil (David Erickson) (08/10/90)

In article <CLAY.90Aug9121901@clio.titan.tsd.arlut.utexas.edu> clay@titan.tsd.arlut.utexas.edu (Clay Johnson) writes:
>In article <1152@cs.nps.navy.mil> erickson@cs.nps.navy.mil (David Erickson) writes:
>
>>   Is there any way to define "=" for a limited private type which is an
>>   access type (which may be null)?  

>I have not done so, but you should be able to `dereference' the "="
>that appears within your overloaded "=" function by using the dotted
>notation, ... 

>	if STANDARD."="(POINTER,null) then ...

>Let me know if this works,
>Clay

This will not work.  As I noted in a previous posting, the basic operators
for a type (including "=") are implicitly defined immediately after the
type declaration, rather than in STANDARD.

-Dave Erickson