comp.lang.ada
 help / color / mirror / Atom feed
* Ada for Data Processing?
@ 1996-10-02  0:00 William Frye
  1996-10-03  0:00 ` Alan Brain
  0 siblings, 1 reply; 6+ messages in thread
From: William Frye @ 1996-10-02  0:00 UTC (permalink / raw)




Is there any one out there whoe can point me towards information and/or
tools to take some of the pain out of doing DP work in Ada.  Some
very common DP situations (e.g. reading in variable format records
with "discriminats that are two or more characters long) seem very
difficult in Ada. (I have just recently started working in an Ada
DP environment without report writing tools already established.)






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

* Re: Ada for Data Processing?
  1996-10-02  0:00 Ada for Data Processing? William Frye
@ 1996-10-03  0:00 ` Alan Brain
  1996-10-05  0:00   ` Keith Thompson
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Brain @ 1996-10-03  0:00 UTC (permalink / raw)



William Frye wrote:
> 
> Is there any one out there whoe can point me towards information and/or
> tools to take some of the pain out of doing DP work in Ada.  Some
> very common DP situations (e.g. reading in variable format records
> with "discriminats that are two or more characters long) seem very
> difficult in Ada. (I have just recently started working in an Ada
> DP environment without report writing tools already established.)

Hmmm.. this seems odd to me, it's one of the easier things in Ada-83.

Here's the absolutely-guarenteed-to-work-always method.

Let's assume you have a 2000 Char record, written by a COBOL, RPG or
Assembler program, way back when.

First, read the thing into a buffer of type BYTE_ARRAY, ie stick it in a
typeless buffer defined only as a whole heap of consecutive memory.

Second, use (Shock Horror) UNCHECKED_CONVERSION on the first
discriminant.

Third, do an assignment to the non-representation-clause-defined base
type, and catch any exceptions raised. (How's that again?...See below
for example fragments)

Type TRAFFIC_LIGHT_TYPE is (Red, Yellow, Green);
Type REPRESENTED_TRAFFIC_LIGHT_TYPE is new TRAFFIC_LIGHT_TYPE;
for REPRESENTED_TRAFFIC_LIGHT_TYPE'SIZE use 16;
for REPRESENTED_TRAFFIC_LIGHT_TYPE use
  ( RED => 16#FE00, YELLOW => 16#00FF, GREEN => 16#EE77);

TARGET : TRAFFIC_LIGHT_TYPE;
SOURCE : REPRESENTED_TRAFFIC_LIGHT_TYPE;

begin

  -- do the unchecked conversion to SOURCE here --
  -- ..

  PARANOIA_BLOCK:

  begin
    TARGET := TRAFFIC_LIGHT_TYPE(SOURCE);
  exception
    when CONSTRAINT_ERROR => -- your data is definitely bad
    -- etc
  end PARANOIA_BLOCK;

..
end
Note that if you had the record stored as "RE", "YE", "GR" then it might
be a better idea to write a simple function that converts the character
representation into a hex code, not strictly neccessary but would
improve readability. Another bananaskin is that some older compilers may
insist on no more than 8 bits for enumerated types. But even then, the
'SIZE clause above should over-ride that. 

Why use a seperate "represented" type for anything coming over I/O?
Firstly, efficiency. The compiler will pick the most eficient
representation for the machine. In the general case, this will not be
the same as the data representation on the line/disk.
Secondly, you may well have a different representation depending on the
device. For example the char string "RE" on the disk may translate into
2#100 for the traffic light controller. You use the same base type -
Traffic Light Type - in either case, but convert to different derived
types for I/O.
Thirdly, if the data comes from outside the system DON'T TRUST IT. Until
you've done some operation - such as a simple type conversion and
assignment - the UNCHECKED conversion is just that. If the data says
"YE" when it's supposed to be "RE", both being valid values, you're out
of luck (at least until you do similar assignments later on). But if it
says "&Z" then you know it's crap. Maybe shifted left 1 bit by a
hardware glitch, maybe corrupted, maybe just not adhering to the spec.

I know whereof I speak, I've had exactly this problem. Any more tips,
will be glad to give.
  
----------------------      <> <>    How doth the little Crocodile
| Alan & Carmel Brain|      xxxxx       Improve his shining tail?
| Canberra Australia |  xxxxxHxHxxxxxx _MMMMMMMMM_MMMMMMMMM
---------------------- o OO*O^^^^O*OO o oo     oo oo     oo  
                    By pulling Maerklin Wagons, in 1/220 Scale




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

* Re: Ada for Data Processing?
  1996-10-03  0:00 ` Alan Brain
@ 1996-10-05  0:00   ` Keith Thompson
  1996-10-11  0:00     ` Alan Brain
  0 siblings, 1 reply; 6+ messages in thread
From: Keith Thompson @ 1996-10-05  0:00 UTC (permalink / raw)



In <32546043.1BF3@dynamite.com.au> Alan Brain <aebrain@dynamite.com.au> writes:
[...]
> Type TRAFFIC_LIGHT_TYPE is (Red, Yellow, Green);
> Type REPRESENTED_TRAFFIC_LIGHT_TYPE is new TRAFFIC_LIGHT_TYPE;
> for REPRESENTED_TRAFFIC_LIGHT_TYPE'SIZE use 16;
> for REPRESENTED_TRAFFIC_LIGHT_TYPE use
>   ( RED => 16#FE00, YELLOW => 16#00FF, GREEN => 16#EE77);

The values given in an enumeration representation clause must satisfy
the predefined ordering relationship of the type (RM95-13.4(6)).

> TARGET : TRAFFIC_LIGHT_TYPE;
> SOURCE : REPRESENTED_TRAFFIC_LIGHT_TYPE;
> 
> begin
> 
>   -- do the unchecked conversion to SOURCE here --
>   -- ..
> 
>   PARANOIA_BLOCK:
> 
>   begin
>     TARGET := TRAFFIC_LIGHT_TYPE(SOURCE);
>   exception
>     when CONSTRAINT_ERROR => -- your data is definitely bad
>     -- etc
>   end PARANOIA_BLOCK;
> 
> ..
> end

If Source contains an invalid value, I don't think there's any guarantee
that the conversion will raise Constraint_Error.  In fact, one could
argue that Program_Error makes more sense (assuming the error is detected
at all).

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Ada for Data Processing?
  1996-10-11  0:00     ` Alan Brain
  1996-10-11  0:00       ` Ken Garlington
@ 1996-10-11  0:00       ` Robert Dewar
  1 sibling, 0 replies; 6+ messages in thread
From: Robert Dewar @ 1996-10-11  0:00 UTC (permalink / raw)



Alan said

"Why? How is this different from any other checked conversion? I see your
point about Program_Error, but would hate to be the guy writing the
compiler code to produce this. But a Constraint_Error is reasonable; and
to write a compiler so as not to do such a check in this instance would
be more work than leaving the check in.
I don't have my LRM handy, but can you see how the wording re
Constraint_Error would not apply here? I can't."


Program_Error is always the more appropriate reaction to a case where
erroneous or bounded error execution is detected by the generated code.





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

* Re: Ada for Data Processing?
  1996-10-11  0:00     ` Alan Brain
@ 1996-10-11  0:00       ` Ken Garlington
  1996-10-11  0:00       ` Robert Dewar
  1 sibling, 0 replies; 6+ messages in thread
From: Ken Garlington @ 1996-10-11  0:00 UTC (permalink / raw)



Alan Brain wrote:

[snip]

> > >   -- do the unchecked conversion to SOURCE here --
> > >   -- ..
> > >
> > >   PARANOIA_BLOCK:
> > >
> > >   begin
> > >     TARGET := TRAFFIC_LIGHT_TYPE(SOURCE);
> > >   exception
> > >     when CONSTRAINT_ERROR => -- your data is definitely bad
> > >     -- etc
> > >   end PARANOIA_BLOCK;
> > >
> > > ..
> > > end
> >
> > If Source contains an invalid value, I don't think there's any guarantee
> > that the conversion will raise Constraint_Error. [snip]
> 
> Why? How is this different from any other checked conversion?

I don't know for sure, but I suspect the answer is related to the following Ada 83
problem:

   type Widget is range 1 .. 10;
   function Unchecked_Widget is new Unchecked_Conversion (Natural, Widget);

   Foo : Widget := Unchecked_Widget(0);

   if Foo not in Widget'Range then
     raise Some_Error;
   end if;

Some compilers would not raise Some_Error, since Foo was expected to always be
in the range of its own type -- thus, the "if" statement was optimized away. Since
the assignment to Foo was erroneous in Ada 83 (as well as Ada 95, apparently),
this was not a compiler bug. In Ada 95, of course, you should be able to write

  if not Foo'Valid then
    raise Some_Error;
  end if;

although technically this is not guaranteed to work for this particular example
either. (The AARM recommends doing the common sense thing here, however.)

> I see your
> point about Program_Error, but would hate to be the guy writing the
> compiler code to produce this. But a Constraint_Error is reasonable; and
> to write a compiler so as not to do such a check in this instance would
> be more work than leaving the check in.

It depends on how the compiler generates the code. For example, I see code
like the following fairly often. Using no particular assembly syntax:

        Load Register_1, SOURCE    -- put contents of SOURCE into a register
        Test Register_1, 16#00FF#  -- compare register contents to 16#00FF#
        If_Equal, YELLOW           -- jump to label YELLOW if register=16#00FF#
        Test Register_1, 16#EE77#
        If_Equal, GREEN
        Store 16#0#, TARGET        -- set TARGET to representation of RED
        GoTo NEXT                  -- move on to next Ada instruction
YELLOW: Store 16#1#, TARGET
        GoTo NEXT
GREEN:  Store 16#2#, TARGET
NEXT:   <something else>

So long as all three of the enums in the type for SOURCE are in the type for TARGET, 
this will be the code. If one or more enums are missing from TARGET, then the 
appropriate store(s) would usually be replaced by a call to the exception handler,
but no additional checks would be required.

Note that only two compares are required to process the three enum values.
It would require the generation of an additional test and jump to separate RED from
the invalid bit patterns, as follows:

        Load Register_1, SOURCE    -- put contents of SOURCE into a register
        Test Register_1, 16#00FF#  -- compare register contents to 16#00FF#
        If_Equal, YELLOW           -- jump to label YELLOW if register=16#00FF#
        Test Register_1, 16#EE77#
        If_Equal, GREEN
        Test Register_1, 16#FE00#  -- new test
        If_Not_Equal, ERROR        -- new jump (could be PROGRAM_ERROR)
        Store 16#0#, TARGET        -- set TARGET to representation of RED
        GoTo NEXT                  -- move on to next Ada instruction
YELLOW: Store 16#1#, TARGET
        GoTo NEXT
GREEN:  Store 16#2#, TARGET
NEXT:   <something else>

If invalid bit patterns can only be generated via erroneous constructs, then the 
compiler vendor can generate less code by assuming that only three bit patterns 
exist in SOURCE.

-- 
LMTAS - "Our Brand Means Quality"
For more info, see http://www.lmtas.com or http://www.lmco.com




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

* Re: Ada for Data Processing?
  1996-10-05  0:00   ` Keith Thompson
@ 1996-10-11  0:00     ` Alan Brain
  1996-10-11  0:00       ` Ken Garlington
  1996-10-11  0:00       ` Robert Dewar
  0 siblings, 2 replies; 6+ messages in thread
From: Alan Brain @ 1996-10-11  0:00 UTC (permalink / raw)



Keith Thompson wrote:
> 
> In <32546043.1BF3@dynamite.com.au> Alan Brain <aebrain@dynamite.com.au> writes:

> > for REPRESENTED_TRAFFIC_LIGHT_TYPE use
> >   ( RED => 16#FE00, YELLOW => 16#00FF, GREEN => 16#EE77);
> 
> The values given in an enumeration representation clause must satisfy
> the predefined ordering relationship of the type (RM95-13.4(6)).

..which is what I get for not compiling my code fragments before
sending. Ta for spotting this. I really should have seen it myself, it's
one of my more common coding errors found in the 1st pass.
 
> > TARGET : TRAFFIC_LIGHT_TYPE;
> > SOURCE : REPRESENTED_TRAFFIC_LIGHT_TYPE;
> >
> > begin
> >
> >   -- do the unchecked conversion to SOURCE here --
> >   -- ..
> >
> >   PARANOIA_BLOCK:
> >
> >   begin
> >     TARGET := TRAFFIC_LIGHT_TYPE(SOURCE);
> >   exception
> >     when CONSTRAINT_ERROR => -- your data is definitely bad
> >     -- etc
> >   end PARANOIA_BLOCK;
> >
> > ..
> > end
> 
> If Source contains an invalid value, I don't think there's any guarantee
> that the conversion will raise Constraint_Error.  In fact, one could
> argue that Program_Error makes more sense (assuming the error is detected
> at all).

Why? How is this different from any other checked conversion? I see your
point about Program_Error, but would hate to be the guy writing the
compiler code to produce this. But a Constraint_Error is reasonable; and
to write a compiler so as not to do such a check in this instance would
be more work than leaving the check in.
I don't have my LRM handy, but can you see how the wording re
Constraint_Error would not apply here? I can't.
 



----------------------      <> <>    How doth the little Crocodile
| Alan & Carmel Brain|      xxxxx       Improve his shining tail?
| Canberra Australia |  xxxxxHxHxxxxxx _MMMMMMMMM_MMMMMMMMM
---------------------- o OO*O^^^^O*OO o oo     oo oo     oo  
                    By pulling Maerklin Wagons, in 1/220 Scale




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

end of thread, other threads:[~1996-10-11  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-10-02  0:00 Ada for Data Processing? William Frye
1996-10-03  0:00 ` Alan Brain
1996-10-05  0:00   ` Keith Thompson
1996-10-11  0:00     ` Alan Brain
1996-10-11  0:00       ` Ken Garlington
1996-10-11  0:00       ` Robert Dewar

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