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
![]()