[net.lang.ada] Quite Limited!

wilson%anchor.DECnet@LLL-ICDC.ARPA ("ANCHOR::WILSON") (09/30/86)

I'm posting this message for a colleague:

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

I have encountered a restriction in the definition of Ada that seems to me
to be overly tight.   When I build an abstract data type using a Limited
Private type and I wish to create an object of that type, I must call a
procedure defined by the abstract data type's implementing package.

The feature of the language specified at LRM 7.4.4 that discomforts me
is that no procedure that is defined outside the package can provide the
object as an OUT parameter.  

The following Ada fragment illustrates the problem:



PACKAGE Try_Lim IS 		-- an abstract data type definition
    TYPE Lim_Type IS LIMITED PRIVATE ; 
    PROCEDURE Make_Lim ( Data : IN Integer ; 
                         Lim  : OUT Lim_Type )  ; 
    -- I expect to provide certain Data, and obtain an object of Lim_Type
PRIVATE
    TYPE Lim_Type IS NEW Integer ; 
END Try_Lim ; 


WITH Try_Lim ; 
PROCEDURE Use_Lim IS 		-- a user of the abstract data type
    Lim : Try_Lim . Lim_Type ; 

    -- I wish to take (possibly complex) input, and use the package 
    -- interface Make_Lim to encapsulate everything into an object


    PROCEDURE Get_Lim ( New_Lim : OUT Try_Lim . Lim_Type )  IS 
..................................^			ERROR MESSAGE
'Out' parameter is in a subprogram or entry that is not declared in the visible
declarations of the same package as limited type Lim_Type in Try_Lim at line 2
[LRM 7.4.4(4)] 

        Data : Integer ; 
    BEGIN
    --  interact to define data
        Try_Lim . Make_Lim ( Data, New_Lim )  ; 
    END Get_Lim ; 
BEGIN
    Get_Lim ( Lim )  ; 
END Use_Lim ; 


It seems to me that the rule in LRM 7.4.4 intends to prevent me from assigning
a value to objects of Lim_type (a worthy goal); however the effect is to make me
choose between a) Using a private (not limited) type, thus allowing any package
user to perform an assignment, or b) Declaring the mode of Get_Lim's  parameter 
to be IN OUT, thus obscuring the reality that Get_Lim causes the creation of
a new object.

I claim that the security against illegitimate assignments to objects of 
Lim_type is assured even if the OUT mode were permitted in contravention
of LRM 7.4.4 because  the OUT mode parameter must be given a value, and
since no assignment is allowed (by an assignment operator), it can only be
obtained from some subordinate procedure's OUT parameter, tracing eventually
back to the legitimate constructor of the object, within the defining package.

I'd be pleased to read discussion on this; perhaps I've overlooked something?

John Woodruff
woodruff.decnet@lll-icdc.arpa
------

Mendal@SIERRA.STANFORD.EDU (Geoff Mendal) (10/03/86)

Concerning mode 'out' on limited formals not defined in
the package spec where the limited type is defined...

The reason for this restriction has to do with data integrity.
Consider the following (semantically invalid) compilation unit:

  with Text_Io;
  procedure Destroy_File (File : out Text_Io.File_Type) is
  begin
    null;
  end Destroy_File;

If pass by reference is used, no problem.  But if pass by copy is
used, watch out: the copy back rule will result in a junk value being
assigned to the actual parameter.  The restriction is meant to
preserve data privacy, and thwart attempts to destroy "limited" values
without the defining package knowing about it.

Note that for mode 'out' parameter associations, copy-in is not required
except for some esoteric cases (see references below).  This is an
important difference between mode 'out' and 'in out'.  In any case,
the fix to your program is simple: use mode 'in out' instead of 'out'.

References:
  LRM: 6.2(6 .. 7); 7.4.4(4)
  Barnes, "Programming in Ada": pp. 125, 132, 340

gom
-------