[comp.lang.modula2] Type Conversion

aplusl@ethz.UUCP (Albert Meier) (07/02/88)

Expires: 
Sender: 
Reply-To: aplusl@bernina.UUCP (Albert Meier)
Followup-To: 
Distribution: comp.lang.modula2
Organization: ETH Zuerich, Switzerland
Keywords: 

Here is now the exact proposal from Pat Terry (SA) and me (CH). We have
been asked to post it. As mentioned before for Switzerland it is the
second choice (the third has been decided in Nice, the first choice is
reconsidering the BSI proposal voted against in Nice). Pat has no access
to Usenet but he kindly greets you all. Here it comes:

To:   Persons interested in type conversions in Modula-2
 
From: Pat Terry, Computer Science, Rhodes University, GRAHAMSTOWN 6140
 
_______________________________________________________________________________________________________________
 
 
 
The Nice ISO standardisation meeting adopted a proposal of mine
concerning
"safe" type conversions, I suspect reluctantly, and with good reason.
The
proposal was motivated mainly by a desire to clear a log-jam, and with
an
eye on what was about to follow (the discussion on the status of ORD,
TRUNC
and FLOAT). Albert Meier and I would like to make a compromise
suggestion.
 
It is of interest to review the various proposals made for safe
conversions.  The position in PIM, I believe, can be summarised in the
following table, which omits the potential complications from range
errors.
 
 
                         To convert an Expression of type
 
                Integer Cardinal    Real    Longreal    Char     Enum
      To a result
      of type
 
      Integer      -       VAL       *         *         *         *
 
      Cardinal    VAL/ORD   -      TRUNC       *        ORD       ORD
 
      Real         *      FLOAT      -         *         *         *
 
      Longreal     *        *        *         -         *         *
 
      Char         *     VAL/CHR     *         *         -         *
 
      Enum         *       VAL       *         *         *         -
 
 
Here the * entries represent "no direct one-step conversion" and the -
entries represent "no conversion needed".  "Enum" means any enumerated
type, including BOOLEAN.
 
In fact, I am not certain how one converts directly from an integer to a
cardinal.  A close reading of PIM suggests that ORD is used, but I have
seen VAL advocated, and I have seen compilers do strange things here
too.
Another viewpoint is that ORD(MIN(INTEGER)) should return 0, but this is
really rather ludicrous, and I do not think anyone would take this
seriously.
 
One is struck with the sparseness of the table.  Some conversions are
really horrible, for example from integer to real.  Presumably one
really
needs code like
 
     IF I > 0 THEN R := FLOAT(ORD(I)) ELSE R := - FLOAT(ORD(ABS(I)) END
 
which would be very tiresome if complicated compound expressions were
needed.
 
One gets the distinct impression that the implementors of the original
compilers never have any need for writing any number-crunching programs
-
or indeed, any that use REAL at all.  One could level the same criticism
at
their total disregard for COMPLEX, but that is a rather different issue.
When I teach students here they are completely amazed at the difficulty
which using REAL seems to present.
 
The BSI proposal for safe conversions, as I can see it (stripped of the
LONGCARD, LONGINT, SHORTINT etc baggage which I think we can agree is a
side issue here), can be summarised in the following table.
 
 
                         To convert an Expression of type
 
                Integer Cardinal    Real    Longreal    Char     Enum
      To a result
      of type
 
      Integer      -     INTEGER   INTEGER   INTEGER     *         *
 
      Cardinal  CARDINAL    -      CARDINAL  CARDINAL  CARDINAL CARDINAL

      Real        REAL     REAL      -        REAL       *         *
 
      Longreal  LONGREAL LONGREAL  LONGREAL    -         *         *
 
      Char         *      CHAR       *         *         -         *
 
      Enum         *      DAYS       *         *         *         -
 
 
 
 
 
The proposal adopted at the Nice meeting can be summarised as follows
 
                         To convert an Expression of type
 
                Integer Cardinal    Real    Longreal    Char     Enum
      To a result
      of type
 
      Integer      -    CONVERT    CONVERT   CONVERT     *         *
 
      Cardinal  CONVERT     -  CONVERT/TRUNC CONVERT  CONVERT/ORD
CONVERT/ORD
 
      Real      CONVERT CONVERT/FLOAT -      CONVERT     *         *
 
      Longreal  CONVERT CONVERT    CONVERT     -         *         *
 
      Char         *    CONVERT/CHR  *         *         -         *
 
      Enum         *    CONVERT      *         *         *         -
 
 
The objection to this is aesthetic - it is very clumsy to use
CONVERT(T,x)
when a nice simple function would look better.  The objections to the
BSI
proposal are really that they introduce new semantics into old syntax.
The
argument in favour of ORD, TRUNC and CHR is that they are familiar and
already part of the language.
 
The point need to be made that the "standard" functions in Modula-2 are
mostly highly non-standard, in that many of them are in fact generic.
Once
this is accepted, there seems no reason why similar functions should not
be
as generic as ORD (which maps "any" ordinal type to CARDINAL), for
example,
and why FLOAT should not be able to map "any" numerical value to REAL.
Admittedly, REAL would be a better name than FLOAT, but that's history
that
we cannot rewrite.
 
The suggestion Albert and I would like to make is summarised in the
following table.  It introduces three new pervasive identifiers INT,
CARD
and LFLOAT.
 
 
                         To convert an Expression of type
 
                Integer Cardinal    Real    Longreal    Char     Enum
      To a result
      of type
 
      Integer      -       INT      INT       INT       INT       INT
 
      Cardinal   CARD/ORD   -     CARD/TRUNC  CARD    CARD/ORD  CARD/ORD

      Real       FLOAT    FLOAT      -        FLOAT      *         *
 
      Longreal   LFLOAT   LFLOAT   LFLOAT      -         *         *
 
      Char       CHR       CHR       *         *         -         *
 
      Enum       CONVERT  CONVERT    *         *         *         -
 
 
CHR, TRUNC and ORD are retained for historical reasons.  The matrix is
now
symmetric, and the usage of CONVERT would probably be minimal in
practice.
CARD could be dispensed with, and ORD used throughout, but CARD and INT
would make a nice pair, with the intent fairly obvious.
 
There is a lurking problem in that if an implementation wants to have
SYSTEM.LONGCARD or SYSTEM.SHORTINT or whatever, this seems to require a
further plethora of names.  However, we could still demand that CARD,
INT,
FLOAT, LFLOAT apply to arguments of any of these types, and would need
only
to  introduce LCARD, LINT, SCARD, SINT and so on.
 
 
 SSS   N   N  V   V      SNV       SWISS STANDARDIZATION BODY
S      NN  N  V   V      149/UK2   Programming Languages
 SSS   N N N  V   V      Chairman  Albert Meier, CH-8906 Bonstetten
    S  N  NN   V V       . E-mail  aplusl@ifi.ethz.(ch/UUCP)
 SSS   N   N    V                  ...mcvax!cernvax!ethz!aplusl

alan@pdn.UUCP (Alan Lovejoy) (07/04/88)

In article <491@ethz.UUCP> aplusl@ethz.UUCP (Albert Meier) writes:
>The proposal adopted at the Nice meeting can be summarised as follows
> 
>                         To convert an Expression of type
> 
>                Integer Cardinal    Real    Longreal    Char     Enum
>      To a result
>      of type
> 
>      Integer      -    CONVERT    CONVERT   CONVERT     *         *
> 
>      Cardinal  CONVERT     -  CONVERT/TRUNC CONVERT  CONVERT/ORD
>CONVERT/ORD
> 
>      Real      CONVERT CONVERT/FLOAT -      CONVERT     *         *
> 
>      Longreal  CONVERT CONVERT    CONVERT     -         *         *
> 
>      Char         *    CONVERT/CHR  *         *         -         *
> 
>      Enum         *    CONVERT      *         *         *         -
>[Another suggestion:] 
>                         To convert an Expression of type
> 
>                Integer Cardinal    Real    Longreal    Char     Enum
>      To a result
>      of type
> 
>      Integer      -       INT      INT       INT       INT       INT
> 
>      Cardinal   CARD/ORD   -     CARD/TRUNC  CARD    CARD/ORD  CARD/ORD
>
>      Real       FLOAT    FLOAT      -        FLOAT      *         *
> 
>      Longreal   LFLOAT   LFLOAT   LFLOAT      -         *         *
> 
>      Char       CHR       CHR       *         *         -         *
> 
>      Enum       CONVERT  CONVERT    *         *         *         -

I have several objections to both of these porposals:

1) What about subrange types?  Simply changing one of the bounds could
make such types change from long to short (or short to long), or from
INTEGER to CARDINAL.  The following code may break: 

  TYPE    

    SubRange1 = [min1..max1];
    SubRange2 = [min2..max2];

  ...

  aValueOfSubRange1 := INT(aValueOfSubRange2);

This code is not portable because it hard-codes the fact that SubRange1
is an INTEGER subrange and that SubRange2 is a CARDINAL subrange.  If
the values of min1, max1, min2 and max2 are system-dependent values,
then the code will certainly be busted as it is ported from system to
system.  On the other hand, if the bounds constants are application
dependent, then the code can not be made generic to all applications.

Better would be the following:

  aValueOfSubRange1 := SubRange1(aValueOfSubRange2);

  -- or even --

  aValueOfSubRange1 := VALUE(aValueOfSubRange2);

Now the code is valid as long as a meaning-preserving conversion is
possible between the two types.  It the two types are the same, then
it is simply a null operation.  If the right-hand-side value is out
of range of the SubRange1, then a run-time exception occurs.

2) The proposals are too complicated with exceptions and different
keywords for a single operation: meaning-preserving conversion.  
Modula-2 is getting too many built-in types to even think about having
a different conversion operator for each possible combination.  Keep it
simple, stupid!  Quick, can you remember which conversions between the
basic types are legal and illegal in the proposals quoted above?


-- 
Alan Lovejoy; alan@pdn; 813-530-8241; Paradyne Corporation: Largo, Florida.
Disclaimer: Do not confuse my views with the official views of Paradyne
            Corporation (regardless of how confusing those views may be).
Motto: Never put off to run-time what you can do at compile-time!  

mrys@ethz.UUCP (Michael Rys) (07/06/88)

On the Ceres workstation developped at the Inst. of Inf. ETH the
standard Modula-2 Compiler defines CARDINAL as subrange of INTEGER,
for the range [MAX(INTEGER)..MAX(CARDINALold)] and further you may use
then LONGINT. In the manual is written that CARDINAL is obsolete and
should therefore be replaced by INTEGER or LONGINT wherever possible.

Cheers...Michael

uucp: mrys@ethz.uucp
IPSANet : mrys@ipsaint

aplusl@ethz.UUCP (Albert Meier) (07/07/88)

In article <500@ethz.UUCP> mrys@bernina.UUCP (Michael Rys) writes:
>On the Ceres workstation developped at the Inst. of Inf. ETH the
>standard Modula-2 Compiler defines CARDINAL as subrange of INTEGER,
>for the range [MAX(INTEGER)..MAX(CARDINALold)] and further you may use
>then LONGINT. In the manual is written that CARDINAL is obsolete and
>should therefore be replaced by INTEGER or LONGINT wherever possible.

As far as I remember we decided in Nice to solve this problem with the
help of 3 constants "z1", "z2" and "z3" that define the bounds of the
basic numeric types. For the ETH single pass compiler, that is also used
on the Ceres this would meen z1=z2<z3, for most other compilers it means
z1<z2<z3.

 SSS   N   N  V   V      SNV       SWISS STANDARDIZATION BODY
S      NN  N  V   V      149/UK2   Programming Languages
 SSS   N N N  V   V      Chairman  Albert Meier, CH-8906 Bonstetten
    S  N  NN   V V       . E-mail  aplusl@ifi.ethz.(ch/UUCP)
 SSS   N   N    V                  ...mcvax!cernvax!ethz!aplusl