comp.lang.ada
 help / color / mirror / Atom feed
* why can't we declare unconstrained objects ?
@ 2004-12-12 15:43 Michael Mounteney
  2004-12-12 17:39 ` Martin Krischik
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Michael Mounteney @ 2004-12-12 15:43 UTC (permalink / raw)


Is there a simple way in Ada of simulating C/C++ unions ?  It seems to
me that this is gratuitously prevented, that is, it can be done with
safety, by extending an existing run-time check, but it is in fact
prevented by the compiler.

Hopefully the following commented source will illustrate my point.

with Ada.text_IO;

procedure unconstrained is

	-- Very simple discriminated type
	type thing (what : Boolean) is
		record
			case what is
				when false =>
					letter : character;
				when true =>
					number : natural;
			end case;
		end record;

	-- No problems here:  we provide a discriminant.
	sample : thing := (false, 'X');

	-- This is alright as well of course.
	type thing_pointer is access all thing;

	-- This is also fine:  a pointer to any `thing'.
	indirect : thing_pointer;

	-- This causes a problem:  I want an unconstrained `thing', one
	-- that can be switched between holding a character and a number
	-- but the initialisation makes it constrained.
	sample2 : thing := (true, 12);

	-- Omitting the initialisation doesn't work:
	-- this just fails at compile-time.
	sample3 : thing;

begin
	-- Just reference a field in the `thing'.
	Ada.text_IO.put (sample.letter);

	-- Create a new access object and access its field
	-- This requires a RUN-TIME check that indirect.what is true.
	indirect := new thing (true);
	indirect.number := 12;

	-- This will generate a RUN-TIME failure of course.
	indirect.letter := 'A';

	-- Warning at compile-time, failure at run-time.  I want to change
the
	-- discriminant.  Since the compiler will insert a run-time check
	-- for field selection via an access, why not for a direct variable ?
	sample2 := thing'(false, 'Z');
end;



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 15:43 why can't we declare unconstrained objects ? Michael Mounteney
@ 2004-12-12 17:39 ` Martin Krischik
  2004-12-12 17:47 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Martin Krischik @ 2004-12-12 17:39 UTC (permalink / raw)


Michael Mounteney wrote:

> Is there a simple way in Ada of simulating C/C++ unions ?  It seems to
> me that this is gratuitously prevented, that is, it can be done with
> safety, by extending an existing run-time check, but it is in fact
> prevented by the compiler.
 
> Hopefully the following commented source will illustrate my point.
> 
> with Ada.text_IO;
> 
> procedure unconstrained is
> 
> -- Very simple discriminated type
> type thing (what : Boolean) is

You need to provide a default:

type thing (what : Boolean := true) is

to get a mutable type.

> record
> case what is
> when false =>
> letter : character;
> when true =>
> number : natural;
> end case;
> end record;

Ada ada will only allocate the minimum needed storrage for the discriminated
types. i.E. for false 8 bit and for true 32 bit and that cannot be changed
later - unless the type is mutable - then the maximum is allocated. 

> -- No problems here:  we provide a discriminant.
> sample : thing := (false, 'X');
> 
> -- This is alright as well of course.
> type thing_pointer is access all thing;
> 
> -- This is also fine:  a pointer to any `thing'.
> indirect : thing_pointer;
> 
> -- This causes a problem:  I want an unconstrained `thing', one
> -- that can be switched between holding a character and a number
> -- but the initialisation makes it constrained.
> sample2 : thing := (true, 12);
> -- Omitting the initialisation doesn't work:
> -- this just fails at compile-time.
> sample3 : thing;

As said, you need a mutable type to do that.

> begin
> -- Just reference a field in the `thing'.
> Ada.text_IO.put (sample.letter);
> 
> -- Create a new access object and access its field
> -- This requires a RUN-TIME check that indirect.what is true.
> indirect := new thing (true);
> indirect.number := 12;
> 
> -- This will generate a RUN-TIME failure of course.
> indirect.letter := 'A';
> 
> -- Warning at compile-time, failure at run-time.  I want to change
> the
> -- discriminant.  Since the compiler will insert a run-time check
> -- for field selection via an access, why not for a direct variable ?
> sample2 := thing'(false, 'Z');
> end;

With Regards

Martin
-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 15:43 why can't we declare unconstrained objects ? Michael Mounteney
  2004-12-12 17:39 ` Martin Krischik
@ 2004-12-12 17:47 ` Dmitry A. Kazakov
  2004-12-12 18:21 ` Martin Dowie
  2004-12-15 13:39 ` David Botton
  3 siblings, 0 replies; 8+ messages in thread
From: Dmitry A. Kazakov @ 2004-12-12 17:47 UTC (permalink / raw)


On 12 Dec 2004 07:43:21 -0800, Michael Mounteney wrote:

> Is there a simple way in Ada of simulating C/C++ unions ?  It seems to
> me that this is gratuitously prevented, that is, it can be done with
> safety, by extending an existing run-time check, but it is in fact
> prevented by the compiler.
> 
> Hopefully the following commented source will illustrate my point.
> 
> with Ada.text_IO;
> 
> procedure unconstrained is
> 
> 	-- Very simple discriminated type
> 	type thing (what : Boolean) is

Provide default:

   type thing (what : Boolean := False) is ...

this will make it...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 15:43 why can't we declare unconstrained objects ? Michael Mounteney
  2004-12-12 17:39 ` Martin Krischik
  2004-12-12 17:47 ` Dmitry A. Kazakov
@ 2004-12-12 18:21 ` Martin Dowie
  2004-12-12 18:40   ` Jeffrey Carter
  2004-12-15 13:39 ` David Botton
  3 siblings, 1 reply; 8+ messages in thread
From: Martin Dowie @ 2004-12-12 18:21 UTC (permalink / raw)


Michael Mounteney wrote:
> Is there a simple way in Ada of simulating C/C++ unions ?  It seems to
> me that this is gratuitously prevented, that is, it can be done with
> safety, by extending an existing run-time check, but it is in fact
> prevented by the compiler.
> 
> Hopefully the following commented source will illustrate my point.
> 
> with Ada.text_IO;
> 
> procedure unconstrained is
> 
> 	-- Very simple discriminated type
> 	type thing (what : Boolean) is

Simply add a default to the discriminant and you can change it all you 
want at run-time (e.g. "what : Boolean := Boolean'First").

Cheers

-- Martin



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 18:21 ` Martin Dowie
@ 2004-12-12 18:40   ` Jeffrey Carter
  2004-12-12 19:24     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 8+ messages in thread
From: Jeffrey Carter @ 2004-12-12 18:40 UTC (permalink / raw)


Martin Dowie wrote:

> Michael Mounteney wrote:
> 
>>     type thing (what : Boolean) is
> 
> Simply add a default to the discriminant and you can change it all you 
> want at run-time (e.g. "what : Boolean := Boolean'First").

To be precise (and it sounds as if the OP needs this level of detail), 
if a discriminated record type has defaults for all discriminants, then 
you can declare an unconstrained object of the type by not specifying 
the discriminants:

type R (D : Boolean := False) is record ...

V : R;
...
V := R'(D => True, ...);

However, if you declare objects with discriminants specified:

X : R (D => False);

then the object is constrained and the discriminant cannot be changed.

Also, you can only change the discriminant by assigning the entire record.

V.D := True; -- illegal

If you're interested in interpreting the same bit pattern as 2 different 
types, this is not the mechanism Ada uses. Use Unchecked_Conversion instead.

-- 
Jeff Carter
"Nobody expects the Spanish Inquisition!"
Monty Python's Flying Circus
22



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 18:40   ` Jeffrey Carter
@ 2004-12-12 19:24     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 8+ messages in thread
From: Dmitry A. Kazakov @ 2004-12-12 19:24 UTC (permalink / raw)


On Sun, 12 Dec 2004 18:40:40 GMT, Jeffrey Carter wrote:

> If you're interested in interpreting the same bit pattern as 2 different 
> types, this is not the mechanism Ada uses. Use Unchecked_Conversion instead.

Right, especially because the value of the discriminant will be a *part* of
the record. Same is true if you'll try to achieve it using class-wide
types. Type tag will be a part of T'Class. In short, Ada maintains
consistency of values and views. Unchecked_Conversion is mainly to
circumvent it.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: why can't we declare unconstrained objects ?
  2004-12-12 15:43 why can't we declare unconstrained objects ? Michael Mounteney
                   ` (2 preceding siblings ...)
  2004-12-12 18:21 ` Martin Dowie
@ 2004-12-15 13:39 ` David Botton
  2004-12-15 21:47   ` Randy Brukardt
  3 siblings, 1 reply; 8+ messages in thread
From: David Botton @ 2004-12-15 13:39 UTC (permalink / raw)


Here is an example from GNATCOM (http://www.gnavi.org) of a C/C++ style union

   subtype Variant_Range is Positive range 1 .. 41;

   --  NOTE: The Which values are completely bogus and have no significance

   --        The type of the variant can not be determined using it

   --        The values bellow do NOT correspond to correct variant type

   --        constants!

   type Variant_Union (Which : Variant_Range := 1) is

      record

         case Which is

            when 1 =>

               lVal      : Interfaces.C.long;

            when 2 =>

               bVal      : Interfaces.C.unsigned_char;

            when 3 =>

               iVal      : Interfaces.C.short;

            when 4 =>

               fltVal    : Interfaces.C.C_float;

            when 5 =>

               dblVal    : Interfaces.C.double;

            when 6 =>

               boolVal   : VARIANT_BOOL;

            when 7 =>

               bool      : VARIANT_BOOL;

            when 8 =>

               scode     : Types.SCODE;

            when 9 =>

               cyVal     : CURRENCY;

            when 10 =>

               date      : Types.DATE;

            when 11 =>

               bstrVal   : BSTR;

            when 12 =>

               punkVal   : Pointer_To_IUnknown;

            when 13 =>

               pdispVal  : Pointer_To_IDispatch;

            when 14 =>

               parray    : Pointer_To_SAFEARRAY;

            when 15 =>

               pbVal     : Pointer_To_BYTE;

            when 16 =>

               piVal     : Pointer_To_short;

            when 17 =>

               plVal     : Pointer_To_long;

            when 18 =>

               pfltVal   : Pointer_To_C_float;

            when 19 =>

               pdblVal   : Pointer_To_double;

            when 20 =>

               pboolVal  : Pointer_To_VARIANT_BOOL;

            when 21 =>

               pbool     : Pointer_To_VARIANT_BOOL;

            when 22 =>

               pscode    : Pointer_To_SCODE;

            when 23 =>

               pcyVal    : Pointer_To_CURRENCY;

            when 24 =>

               pdate     : Pointer_To_DATE;

            when 25 =>

               pbstrVal  : Pointer_To_BSTR;

            when 26 =>

               ppunkVal  : Pointer_To_Pointer_To_IUnknown;

            when 27 =>

               ppdispVal : Pointer_To_Pointer_To_IDispatch;

            when 28 =>

               pparray   : Pointer_To_Pointer_To_SAFEARRAY;

            when 29 =>

               pvarVal   : Pointer_To_VARIANT;

            when 30 =>

               byref     : Pointer_To_Void;

            when 31 =>

               cVal      : Interfaces.C.char;

            when 32 =>

               uiVal     : Interfaces.C.unsigned_short;

            when 33 =>

               ulVal     : Interfaces.C.unsigned_long;

            when 34 =>

               intVal    : Interfaces.C.int;

            when 35 =>

               uintVal   : Interfaces.C.unsigned;

            when 36 =>

               pdecVal   : Pointer_To_DECIMAL;

            when 37 =>

               pcVal     : Pointer_To_char;

            when 38 =>

               puiVal    : Pointer_To_unsigned_short;

            when 39 =>

               pulVal    : Pointer_To_unsigned_long;

            when 40 =>

               pintVal   : Pointer_To_int;

            when 41 =>

               puintVal  : Pointer_To_unsigned;

         end case;

      end record;

   pragma Convention (C_Pass_By_Copy, Variant_Union);

   pragma Unchecked_Union (Variant_Union);



   Size_Of_VARIANT : constant := 128;



   type VARIANT is

      record

         vt         : VARTYPE;

         wReserved1 : Interfaces.C.unsigned_short;

         wReserved2 : Interfaces.C.unsigned_short;

         wReserved3 : Interfaces.C.unsigned_short;

         u          : Variant_Union;

      end record;

   for VARIANT'Size use Size_Of_VARIANT;

   pragma Convention (C_Pass_By_Copy, VARIANT);

   --  The automation type VARIANT is used to create a variable that

   --  can contain any of the OLEAUTOMATION types. The value of vt

   --  indicates the type currently held in the type union in u

   --  Variants should be manipulated using the Variant APIs or with

   --  GNATCOM.Variant



   type Pointer_To_VARIANT_Constant is access constant VARIANT;





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

* Re: why can't we declare unconstrained objects ?
  2004-12-15 13:39 ` David Botton
@ 2004-12-15 21:47   ` Randy Brukardt
  0 siblings, 0 replies; 8+ messages in thread
From: Randy Brukardt @ 2004-12-15 21:47 UTC (permalink / raw)


"David Botton" <david@botton.com> wrote in message
news:2004121508394116807%david@bottoncom...
> Here is an example from GNATCOM (http://www.gnavi.org) of a C/C++ style
union
...

Note that pragma Unchecked_Union is in Ada 2005, and several compilers
already support it. But if you're not using one of them, you can't do it
this way.

Our experience with Claw was that there wasn't many cases where you really
needed a Union. Most of the time, careful declarations avoided the need.
When we really did need a Union, we used Unchecked_Conversion. YMMV.

                                Randy.





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

end of thread, other threads:[~2004-12-15 21:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-12-12 15:43 why can't we declare unconstrained objects ? Michael Mounteney
2004-12-12 17:39 ` Martin Krischik
2004-12-12 17:47 ` Dmitry A. Kazakov
2004-12-12 18:21 ` Martin Dowie
2004-12-12 18:40   ` Jeffrey Carter
2004-12-12 19:24     ` Dmitry A. Kazakov
2004-12-15 13:39 ` David Botton
2004-12-15 21:47   ` Randy Brukardt

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