The ModulaTor logo 7KB

The ModulaTor

Oberon-2 and Modula-2 Technical Publication

The ModulaTor
Erlangen's First Independent Modula_2 Journal! Nr. 7/Aug-1991 
_____________________________________________________________

How to improve acceptance of ISO-Modula_2? 

by Guenter Dotzel, ModulaWare 

Whether ISO-Modula_2 will gain acceptance by the programmer community depends on many factors. 
There are some design decissions in the ISO-Modula_2 language as well as in its standard library made by 
the international standardisation comittee which gives ISO-Modula_2 the appearance of an academic 
exercise (i.e. over-engineered). 

1. To start with the language's name: Modula-2 is not a valid identifier in Modula-2; it has to be renamed to 
Modula_2 (just a joke). 

2. My request to the Modula_2-DIN-standardisation working group to rename/shorten 
some of the ISO-Modula_2 library modules' names to a convenient name length was 
rejected. We now have the module names SYSTEM, COROUTINES, EXCEPTIONS, 
Termination, Storage, CharClass, Processes, Semaphores, Strings, RealMath, 
LongMath, ComplexMath, LongComplexMath, WholeIO, RealIO, LongIO, TextIO, BinIO, 
IORes, SWholeIO, SRealIO, SLongIO, STextIO, SBinIO, SIORes, StdChans, 
ProgramArgs, SeqStream, RndFile, RewFile, Terminal, IOLink, DevConsts, IOChannel, 
IOConsts, LowReal, LowLong, ConvTypes, WholeConv, RealConv, LongConv, 
SysClock. Besides the fact, that there are too many modules, the name length problem 
and some other aspects are discussed in the following. 

3. My request to introduce unique names for the mathematical functions in different 
modules was rejected. 

4. My request to add a pervasive conversion function from COMPLEX to 
LONGCOMPLEX data type was rejected. You could easily define these functions 
yourself; of course, by getting some performance loss compared to a build-in function: 

PROCEDURE CTOLC (c: COMPLEX): LONGCOMPLEX;
BEGIN
  RETURN CMPLX(LFLOAT(RE(c)), LFLOAT(IM(c)));
END CTOLC;

PROCEDURE LCTOC (c: LONGCOMPLEX): COMPLEX;
BEGIN
  RETURN CMPLX(FLOAT(RE(c)), FLOAT(IM(c)));
END LCTOC;

If you define these functions CTOLC and LCTOC in every module where such 
conversions are needed you'll end up in stupid repetitions. On the other hand, if you 
define these functions in a utility library module, you are free to call them RCMPLX and 
LCMPLX or ConvertComplexToLongComplex and ConvertLongComplexToComplex. 
What are your favorite names? For all other data types, there exist build-in conversion 
functions except for [LONG]COMPLEX. So why did ISO-M2 exclude them? Answer by 
the comittee: (1) those functions are easily implemented by any programmer and (2) 
both functions are rarely needed. How could they know? 

5. My request to add hyperbolic functions in the mathematical libraries was rejected, 
since it would be easy for the programmer, to define these functions using exp. This is 
not true, except for certain trivial argument ranges! If you try to implement sinh, cosh, 
tanh using the mathematical definitions of a textbook, you'll get rounding errors in certain 
argument ranges, which make the functions useless. It is especially difficult to implement 
a correct tanh. To illustrate how complicated tanh is, I like to show my recursive 
implementation in Modula_2 (no warranty is given! Does anybody have a simpler 
method except for using LONGREAL internally?): 

  PROCEDURE tanh( R1 : REAL ): REAL;
  VAR e2, x2, LO,B, tanhLO, x: REAL;
  CONST (*HIn=1.0/2.0+n/16.0+1.0/32.0; TanHIn=tanh(HIn); Cn=1-TanHIn*TanHIn*)
    HI0=0.53125; TanHI0=0.48633604; C0=1.0-TanHI0*TanHI0;
    HI1=0.59375; TanHI1=0.53258728; C1=1.0-TanHI1*TanHI1;
    HI2=0.65625; TanHI2=0.57586240; C2=1.0-TanHI2*TanHI2;
    HI3=0.71875; TanHI3=0.61613440; C3=1.0-TanHI3*TanHI3;
    HI4=0.78125; TanHI4=0.65342359; C4=1.0-TanHI4*TanHI4;
    HI5=0.84375; TanHI5=0.68779020; C5=1.0-TanHI5*TanHI5;
    HI6=0.90625; TanHI6=0.71932749; C6=1.0-TanHI6*TanHI6;
    HI7=0.96875; TanHI7=0.74815444; C7=1.0-TanHI7*TanHI7;
    r3=-1.0/3.0; r5=2.0/15.0; r7=-17.0/315.0; r9=62.0/2835.0;
  BEGIN
    x:=ABS(R1);
    IF x < 0.0002441406 THEN RETURN R1
    ELSIF x < 0.5 THEN x2 := x*x;
      RETURN (((r9*x2+r7)*x2+r5)*x2+r3)*x2*R1+R1
    ELSIF x<HI0 THEN LO:=R1-HI0; tanhLO:=tanh(LO); B:=1.0+TanHI0*tanhLO;
      RETURN TanHI0+tanhLO*C0/B;
    ELSIF x<HI1 THEN LO:=R1-HI1; tanhLO:=tanh(LO); B:=1.0+TanHI1*tanhLO;
      RETURN TanHI1+tanhLO*C1/B;
    ELSIF x<HI2 THEN LO:=R1-HI2; tanhLO:=tanh(LO); B:=1.0+TanHI2*tanhLO;
      RETURN TanHI2+tanhLO*C2/B;
    ELSIF x<HI3 THEN LO:=R1-HI3; tanhLO:=tanh(LO); B:=1.0+TanHI3*tanhLO;
      RETURN TanHI3+tanhLO*C3/B;
    ELSIF x<HI4 THEN LO:=R1-HI4; tanhLO:=tanh(LO); B:=1.0+TanHI4*tanhLO;
      RETURN TanHI4+tanhLO*C4/B;
    ELSIF x<HI5 THEN LO:=R1-HI5; tanhLO:=tanh(LO); B:=1.0+TanHI5*tanhLO;
      RETURN TanHI5+tanhLO*C5/B;
    ELSIF x<HI6 THEN LO:=R1-HI6; tanhLO:=tanh(LO); B:=1.0+TanHI6*tanhLO;
      RETURN TanHI6+tanhLO*C6/B;
    ELSIF x<HI7 THEN LO:=R1-HI7; tanhLO:=tanh(LO); B:=1.0+TanHI7*tanhLO;
      RETURN TanHI7+tanhLO*C7/B;
    ELSIF x < 10.0 THEN
      e2 := exp( 2.0 * R1 );
      RETURN ( e2 - 1.0 ) / ( e2 + 1.0 );
    ELSIF R1 >= 0.0 THEN RETURN 1.0
    ELSE RETURN -1.0
    END;
  END tanh;

The comittee has two arguments against the addition of hyperbolic functions: (1) if a 
programmer has problems to implement a correct tanh, she/he would also have other 
serious numerical problems in her/his application program and last but not least, (2) to let 
room for the software market of add-on libraries. But what about programmers simply 
porting software from another language to Modula_2? Should portation work be done 
only by specialists in numerics or should the numerically-untrained programmer buy 
add-on libraries. What about the quality of add-on library modules? Are ISO-M2 add-on 
library supplier required to deliver ISO-M2 like semantic definitions? Do they handle 
exceptions consistently? 

6. The length of module names: Especially the module name LongComplexMath is too 
long. Instead the M2-DIN-group decided to rename LongMath to LongRealMath to be 
systematic in naming the modules (but the ISO-group did not follow that decision for the 
4th WD). Now both names are too long! So why shouldn't we rename SeqStream, 
RndFile, RewFile to SequentialFile, RandomFile, RewindableFile, when module name 
length is not an issue? 

The problem with long module names is, that if you import e.g. sin from LongMath and 
also from LongComplexMath in the same module and if the functions contained in 
different libraries have identical names, you must use one of the functions in qualified 
mode, e.g.: r := sin(rx); c := LongComplexmath.sin(cx); The latter form is unacceptable, 
since it is too long and makes the program unreadable. 

The argument against shortening names was that the programmer could easily 

IMPORT LongComplexMath; FROM RealMath IMPORT sin; 

and define 

CONST dcsin = LongComplexMath.sin; 

The constant declaration above is procedure renaming in ISO-M2 (a feature which is 
controversial itself, because a procedure name isn't a constant). For an application 
programmer this would be a nightmare. Shown below is the complete mathematical 
library defined this way. 

  IMPORT RealMath, LongMath, ComplexMath, LongComplexMath;

  TYPE (* enumerations *)
    RMathException = RealMath.RMathException;
    dRMathException = LongMath.RMathException;
    (* both types above are defined identically, but are incompatible *)

    CMathLibException = ComplexMath.CMathLibException;
    dCMathLibException = LongComplexMath.CMathLibException;
    (* both types above are defined identically, but are incompatible *)

  CONST (* constants *)
    pi = RealMath.PI; (* RR-type, could be used with LongMath *)
    exp1 = RealMath.Exp1; (* RR-type, could be used with LongMath *)

  CONST (* CC-types, can be used with LongComplexMath (i = CMPLX (0.0, 1.0);) *)
    ci = ComplexMath.i; (* or would you prefer simply i or c_i? *)
    czero =  ComplexMath.zero;
    cone =  ComplexMath.one;

  CONST (* procedures *)
    sqrt = RealMath.sqrt; (* or would you prefer sqrt, d_sqrt, c_scrt, dc_sqrt*)
    dsqrt = LongMath.sqrt;
    csqrt = ComplexMath.sqrt;
    dcsqrt = LongComplexMath.sqrt;
    exp = RealMath.exp;
    dexp = LongMath.exp;
    cexp = ComplexMath.exp;
    dcexp = LongComplexMath.exp;
    ln = RealMath.ln;
    dln = LongMath.ln;
    cln = ComplexMath.ln;
    dcln = LongComplexMath.ln;
    sin = RealMath.sin;
    dsin = LongMath.sin;
    csin = ComplexMath.sin;
    dcsin = LongComplexMath.sin;
    cos = RealMath.cos;
    dcos = LongMath.cos;
    ccos = ComplexMath.cos;
    dccos = LongComplexMath.cos;
    tan = RealMath.tan;
    dtan = LongMath.tan;
    ctan = ComplexMath.tan;
    dctan = LongComplexMath.tan;
    arcsin = RealMath.arcsin;
    darcsin = LongMath.arcsin;
    carcsin = ComplexMath.arcsin;
    dcarcsin = LongComplexMath.arcsin;
    arccos = RealMath.arccos;
    darccos = LongMath.arccos;
    carccos = ComplexMath.arccos;
    dcarccos = LongComplexMath.arccos;
    arctan = RealMath.arctan;
    darctan = LongMath.arctan;
    carctan = ComplexMath.arctan;
    dcarctan = LongComplexMath.arctan;
    power = RealMath.power;
    dpower = LongMath.power;
    cpower = ComplexMath.power;
    dcpower = LongComplexMath.power;
    round = RealMath.round;
    dround = LongMath.round;
    cabs = ComplexMath.abs;
    dcabs = LongComplexMath.abs;
    carg = ComplexMath.arg;
    dcarg = LongComplexMath.arg;
    conj = ComplexMath.conj;
    dconj = LongComplexMath.conj;
    cpolar = ComplexMath.polarToComplex;
    dcpolar = LongComplexMath.polarToComplex;
    cscalarMult = ComplexMath.scalarMult;
    dcscalarMult = LongComplexMath.scalarMult;
    MathException = RealMath.MathException;
    dMathException = LongMath.MathException;
    cMathException = ComplexMath.MathException;
    dcMathException = LongComplexMath.MathException;

Should the programmer include the definitions needed at the top of her/his program. Or 
shoud she/he create a definition module possibly called Math, which contains the 
complete math library? Should everybody do so if she/he doesn't like to define things 
more than once? So why shouldn't ISO-M2 include such a definition to get unique and 
identical names accross all implementations? 

__________________________________________________________________________________________________ 

Report from the Sixth ISO SC22/WG13 Modula_2 Working Group Meeting 

by Guenter Dotzel, ModulaWare GmbH

The sixth ISO-Modula_2 working group meeting, attended by 30 members from 14 
different countries was helt at the University of Tuebingen from July 1. to 5., 1991. This is 
a short summary of the most important changes and addition to the 4th Interim 
ISO-Modula_2 Working Draft Proposal that have been agreed upon at this meeting. The 
new document produced by the so-called drafters is called the 4th Working Draft 
(CD10514-2) and shall be ready in Sep-1991. After a voting period of three months, 
there will be a six months review period before the final paper, called the BFD (big fat 
document) can be produced. 

0. Requirements
 

The minimal requirements for a conforming compiler implementation (such as minimum 
nesting level for procedure declarations) were defined. These values depend on the size 
of WORD. 

1. Language changes
 

BITSET previously moved to module SYSTEM is now again a pervasive type. 

2. I/O-Library identifier renamings 

    4th Interim WD ----> 4th WD

    ___________________________________
    type IOConsts.ReadResultEnum ---> ReadResults
    type DevConsts.OpenResultEnum ---> OpenResults
    type DevConsts.FlagEnum ---> ChanFlags
    module DevConsts ---> ChanConsts
    module Terminal ---> TermFile
    module [S]BinIO ---> [S]RawIO
    module [S]IORes ---> [S]IOResult
    module SeqStream ---> StreamFile
    module RewStream ---> SeqFile
    procedure [S]TextIO.ReadLine ---> ReadRestLine
    procedure [S]TextIO.ReadLn ---> SkipLine
    procedure [S]TextIO.LongIO.ReadLong ---> ReadReal
    procedure [S]TextIO.LongIO.WriteLong ---> WriteReal
    procedure [S]TextIO.LongIO.WriteLongFloat ---> WriteFloat
    procedure [S]TextIO.LongIO.WriteLongFixed ---> WriteFixed
    procedure [S]TextIO.LongIO.WriteLongEnd ---> WriteEng
    type RndFile.RndFileExceptionEnum ---> RndFileExceptions
    procedure IOChannel.BadChan ---> InvalidChan
    procedure IOChannel.BinRead ---> RawRead
    procedure IOChannel.BinWrite ---> RawWrite
    parameter of IOChannel.TextWrite chars ---> charsToWrite
    parameter of IOChannel.BinWrite/RawWrite locs ---> locsToWrite
    type IOChannel.ChanExceptionsEnum ---> ChanExceptions
    type IOChannel.Flags ---> CurrentFlags
    module IOChannel ---> IOChan
    procedure ProgramArgs.ArgGiven ---> IsArgPresent

Furthermore, module IOChannel is no longer responsible for closing all open channels at 
program termination. 

3. Module Strings
 

Constant BigStringCapacity and type BigString deleted 

4. Language extension & modules Exceptions and Termination
 

The syntax of Modula-2 for module block and block was extended by the keywords 
EXCEPT and FINISH and a new statement RETRY for the except-part.
 

module block = declarations, ["BEGIN", statement sequence ["FINISH", statement 
sequence] ["EXCEPT", statement sequence] ], "END";
 

block = declarations, "BEGIN", statement sequence ["EXCEPT", statement sequence], 
"END";
 

The procedures EXCEPTIONS.POPHANDLER, PUSHHANDLER, RETRY and 
ACKNOWLEDGE and the procedure Termination.RegisterCleanUp were deleted. 

5. Language extension & module SYSTEM
 

- new constant BITSPERLOC added
 

- type BITNUM and constant BITSPERBITSET removed
 

- new keyword PACKEDSET that is can be used instead of SET to define a bit set (with 
defined mapping of 2
0
 = bit 0). The minimal number of set elements in PACKEDSET 
shall be equivalent to the size of the largest pervasive type (e.g. 128 with LONG- 
COMPLEX)
 

- type BITSET is defined as PACKEDSET OF [0..BITSPERLOC*LOCSPERWORD-1]
 

The mapping of bits in bit sets is now defined in terms of an abstract binary number 
system. This solves the bit mapping consistency accross implementations for both, little- 
and big-endian machines.
 

- SHIFT and ROTATE apply only to packed sets and must work on at least BITSET
 

- ADDRESSVALUE may cause an exception
 

- ADDADR, SUBADR and DIFADR accept parameters of type ADDRESS and pointers
 

- type BYTE should be provided if appropriate for the machine
 

- note, that neither procedures nor function from module SYSTEM can be assigned to a 
variable or equated to a constant identifier. 

6. Module CharClass
 

PROCEDURE IsWhiteSpace (ch: CHAR): BOOLEAN was added; it returns true if ch is 
either a space character or a member of an implemenation-defined set of format effector 
characters. 

7. String Conversions
 

Three modules from an earlier proposal (D106) were added. Now there are six modules: 
three high-level modules WholeStr, RealStr and LongStr that provide simple string 
conversions (the parameters nextIndex and alignment were dropped) and three 
low-level modules WholeConv, RealConv and LongConv that provide the so-called 
scanner modell which is more flexible but not as easy to use as the *Str procedures. In 
the *Conv modules, the procedure names Scan, Format and Value were renamed to 
reflect the parameter type, e.g. RealConv.Scan is renamed in ScanReal. The 
procedures Take and Give were removed, because their functionality is provided in the 
higher-level *Str modules. 

8. The Complex Math-Library was extended and now includes abs, arg, conj, power, 
sqrt, exp, ln, sin, cos, tan, arcsin, arccos, arctan, polarToComplex, scalarMult, but still no 
hyperbolic functions. 

9. An example using the ISO-Modula_2 I/O-Library of the 4th working draft
 

The program asks for a file name, opens a text file for reading, reads one real number 
per line from a text file and displays the numbers on the terminal using the so-called 
simple I/O-modules SLongIO and STextIO that write directly to the standard output 
channel. Note, that there is no end-of-file equivalent which would allow to write WHILE 
NOT Eof (cid) DO ... END.  

MODULE IO_Library_Example;
(* uses the 4th working draft of ISO-Modula_2, 11-Jul-1991 *)
FROM IOResult IMPORT ReadResults, ReadResult;
FROM StreamFile IMPORT read, text, ChanId, Open, Close, OpenResults;
FROM TextIO IMPORT SkipLine;
FROM LongIO IMPORT ReadReal;
FROM STextIO IMPORT ReadRestLine, WriteString, WriteLn;
FROM SLongIO IMPORT WriteReal;
CONST width = 10;
VAR cid: ChanId; filename: ARRAY[0..254] OF CHAR;
  ores: OpenResults; rres: ReadResults; long: LONGREAL;
BEGIN
  REPEAT WriteString('Please enter a filename'); 
    ReadRestLine(filename); WriteLn; IF LENGTH(filename)=0 THEN RETURN END;
    Open(cid, filename, read + text, ores);
  UNTIL ores = opened;
  LOOP
    ReadReal(cid, long); 
    IF ReadResult(cid) <> allRight THEN EXIT END;
    SkipLine(cid); WriteLong(long, width); WriteLn;
  END;
  Close(cid);
END IO_Library_Example.

__________________________________________________________________________________________________ 

LECTOR/PostScript, File dw2:isotue.dw2, 14-Oct-1991. 
 


IMPRESSUM: The ModulaTor is an unrefereed journal. Technical papers are to be taken as working papers and personal rather than organizational statements. Items are printed at the discretion of the Editor based upon his judgement on the interest and relevancy to the readership. Letters, announcements, and other items of professional interest are selected on the same basis. Office of publication: The Editor of The ModulaTor is Guenter Dotzel; he can be reached by tel/fax: [removed due to abuse] or by mailto:[email deleted due to spam]
  ModulaWare home page   The ModulaTor download    [Any browser]

Webdesign by www.otolo.com/webworx, 14-Jul-1998