Erlangen's First Independent Modula_2 Journal! Nr. 5/Jun-1993
_____________________________________________________________
Submission for the First "Co-operative" Oberon-2 Standardisation Meeting,
20/21-Jun-1993, London
Oberon-2 Standardisation Proposal
by Guenter Dotzel, 05-May-1993, 2nd ed. 06-May-1993
The goal should be to standardise the Oberon-2 language and not the Oberon System.
The Oberon-2 language should allow migration from and interoperability with other
languages such as ISO Modula-2.
1. Language
To get the Oberon-2 Standard out as soon as possible no extensions (except for those
mentioned in Chapter 3 below) should be made to the language defined by
M~ossenb~ock's ETH-Report 160, revised May-1992. Since the Report 160 is not specific
enough I propose to take the exact language semantics from Regis Crelier's OP2
portable compiler front-end and to clarify all ambiguities of the language report.
Although OP2 undergoes maintenance, it was rock-solid since end of 1991. Without OP2
it is nearly impossible to implement an Oberon-2 compiler which is fully ETH-conformant.
2. Library
To avoid delays in standardising the library, the Oberon-2 Standard should adopt the full
set of the ISO Modula-2 library (2nd CD). The few changes required to be able to define
the Oberon-2 interface modules are documented in The ModulaTor, Sep-1992. This
issue also contains the complete listing of the Oberon-2 interface modules for the ISO
M2 Std Lib, except for module [Long]ComplexMath.
To support the modules ComplexMath and LongComplexMath, ISO Modula-2's
pervasive types COMPLEX and LONGCOMPLEX and ISO M2's pervasives procedures
RE, IM and CMPLX could be provided through an additional library module Complex.
[Ed. note/2nd ed.: The 1st ed. of this article proposed to declare COMPLEX and
LONGCOMPLEX as record types and to export associated functions as well as type
bound procedures. Later I found out that the complex data types must be known by (i.e.:
built into) the compiler (see also 4.2 below) to be able to comply to the standard
procedure calling conventions (at least on OpenVMS Alpha).]
In our VAX/VMS Oberon-2 compiler project H2O, we've made good experiences in using
the ISO M2 Std Lib in Oberon-2.
2.1. Library extension: Persistent objects support
Persistent objects should be supported by a required separate library module with the
functionality of the module Objects_Types (see Apendix). A detailed description and
discussion of persistent objects support is contained in The ModulaTor, Feb-1993 which
is further illustrated in the OO-Extension proposal of ISO Modula-2 in The ModulaTor,
May-1993.
3. Extensions and clarifications
Compile- and run-time semantics should be clarified. A comprehensive collection of
ambiguities can be found in The ModulaTor, Apr-1993.
Upward compatible extensions of Oberon-2 could be made later after the
standardisation is finished or at least made substantial progress.
Once, we've agreed not to extend the language in the first phase of standardisation
process, there are only a few language changes required to clean-up the language,
mainly in order to make it interoperable with the ISO Modula-2 language and library,
namely
3.1. allow structured function return values as in ISO Modula-2. This is required to be
able to properly declare the library procedure RndFile.FilePos.
3.2. allow underscores "_" anywhere in identifiers as in ISO Modula-2.
3.3. for compatibility with any type, check-out whether the restriction to open array
parameter of SYSTEM.BYTE being variable parameter could be dropped.
3.4. SYSTEM.CAST should be introduced with the semantics of ISO Modula-2 (take
minimal type length of both parameters)
3.5. non-portable, processor-specific procedures in module SYSTEM (e.g.:
SYSTEM.CC, BIT, LSH) should be eliminated.
3.6. pervasive function procedure ASH should be renamed to SHIFT. Alternatively
SHIFT could be placed in SYSTEM.
3.7. introduce the additional pervasive procedure ASSERT(b: BOOLEAN) which is
already contained in OP2.
3.8. the different pervasive integer types SHORTINT and LONGINT should be renamed
and put into module SYSTEM. For language interoperability with ISO Modula-2's
enumeration and subrange types, integers with different size are still needed; Module
SYSTEM should therefor export the integer types INTEGER_8, INTEGER_16,
INTEGER_32, and INTEGER_64. The pervasive type INTEGER should have
implementation defined size as in ISO Modula-2 (e.g. 32 Bit on a 32 Bit processor,
identical to SYSTEM.INTEGER_32).
3.9. there are some other minor unconveniences (such as SYSTEM.ADR() having
LONGINT type) which should be discussed and cleaned-up by an ad-hoc
SYSTEM-module working group.
3.10. allow recursive procedure types as in ISO Modula-2 (required e.g. in library module
ConvTypes).
3.11. provide a parameter specification mechanism (syntax) for Oberon-2 interface
modules to foreign languages (such as ISO Modula-2) to indicate that no type-descriptor
is expected in case of variable parameter of record type. The symbol "-" could serve this
purpose as parameter name suffix (if the symbol "-" is to be reserved for read-only
parameters use the symbol "/"), e.g.: PROCEDURE p (VAR r-, s- : RecordType).
4. Possible future language extensions
The following extensions should to be considered after the standardisation is finished:
4.1. remove the necessity for the "D"-scale factor in long real literals and introduce
RR-real number literals as in ISO Modula-2.
4.2. provide complex arithmetic support as in ISO M2: introduce new pervasive types
COMPLEX and LONGCOMPLEX, new pervasive function procedures CMPLX, RE, and
IM and allow the operators +, -, *, /, =, # and negation to be applied to complex type
operands.
4.3. introduce the additional pervasive function procedure LENGTH for strings with ISO
Modula-2's semantic.
4.4. in addition to ENTIER, introduce the additional pervasive function procedure INT
with ISO Modula-2's semantic.
4.5. introduce long sets to allow a set of CHAR or introduce the pervasive type
LONGSET with MAX(LONGSET) equal to the number of bits of the largest pervasive
type (i.e. LONGCOMPLEX) as in ISO Modula-2.
4.6. optionally introduce additional integer operators "REM" and "IDIV" with the
semantics of the ISO Modula-2 operators "REM" and "/" for integers.
5. Possible future library extensions:
The following extensions should to be considered after the standardisation of the
Oberon-2 interface modules for the ISO M2 Std Lib is finished:
5.1. provide explicit disposal of dynamic objects for implementation without garbage
collector (see module Objects_Types below).
5.2. Design an object-oriented library based on the structure of the ISO Modula-2
Standard Library.
6. References:
Information how to get electronic edition of The ModulaTor is included in the impressum
below.
7. Appendix
___________________________________________________________________
DEFINITION MODULE Objects_Types;
(*
Run-time type information to support persistent objects.
Compiler supported object registration and
and type-name processing.
A2O|H2O (ModulaWare's AXP|VAX/VMS Oberon-2 Compiler Implementation)
If preconditions specified are not fulfilled, HALT(20) is called.
13-Jan-1993/hG/GD: designed based on ETH-Zuerich's module Type.
05-Apr-1993/pF: procedures DisposeObj, Sizeof added.
04-Nov-1994/hG/GD: procedure DisposeDynArray added.
*)
CONST maxIdentLen* = 32;
TYPE
Object* = POINTER TO ObjectDesc;
ObjectDesc* = RECORD END;
Type* = POINTER TO TypeDesc;
PROCEDURE TypeOf * (o: Object): Type;
(* returns the dynmaic type of object o.
*)
PROCEDURE TypeName * (typ: Type; VAR module, name: ARRAY OF CHAR);
(* returns the source level module and record name of type t.
module and name are filled from LENGTH() to LEN()-1 with CHR(0).
Precondition: typ # NIL.
*)
PROCEDURE This * (module, name: ARRAY OF CHAR): Type;
(* If an object with the name "module.name" was registered,
it returns the pointer type of "module.name"
otherwise NIL is returned.
*)
PROCEDURE NewObj * (VAR o: Object; t: Type);
(* creates an object depending on the dynamic type of t.
A2O|H2O implementation details:
Allocation is performed by calling SYSTEM.NEW, which in
H2O calls LIB$GET_VM. In A2O this is a call to Storage.ALLOCATE,
which usually also calls the OpenVMS system library routine
LIB$GET_VM.
Precondition: t # NIL.
*)
PROCEDURE SizeOf * (o: Object) : LONGINT;
(* returns the number of bytes allocated to the dynamic type of the object o,
not counting the size of the type tag which is equal to SIZE(SYSTEM.PTR).
Precondition: o # NIL.
*)
PROCEDURE DisposeObj * (VAR o: Object);
(* disposes an object o pointing to any extension of Objects_Types.ObjectDesc
depending on the dynamic type of o (including the storage occupied by the
type tag).
A2O|H2O implementation detail:
Deallocation is peformed by calling Storage.DEALLOCATE, which usually
calls the OpenVMS system library routine LIB$FREE_VM.
Precondition: o # NIL, postcondition: o = NIL.
*)
PROCEDURE DisposeDynArray * (VAR o: SYSTEM.PTR;
numDims, elemSize: LONGINT);
(* dispose a Oberon-2 dynamic array with numDims dimensions and elemSize
element size. o is a pointer variable to a n-dimensional dymamic array
such as VAR o: POINTER TO {ARRAY OF}_n T;
DisposeDynArray(o, n, SIZE(T)); disposes the dynamic array o including
its array descriptor.
Precondition: o # NIL, postcondition: o = NIL
In A2O, this procedure does not have the parameters numDims, elemSize;
their values are known from the array descriptor.
*)
PROCEDURE StoreModObjects * (typeDescBase, objects: SYSTEM.PTR);
(*
A call to StoreModObjects is generated by the Oberon-2 compiler in
module body of any Oberon-2 program to register the module's record types.
Run-time type information can be processed with the procedures
TypeOf, TypeName, This, Sizeof and DisposeObj for all objects which are an
extension of type Object.
H2O implementation detail:
In H2O, the call is actually performed indirectly by the run-time procedure
mod$storemodobjects contained in MODRTS.mar (part of H2ORTS.OLB)
*)
END Objects_Types.
__________________________________________________________________
ModulaTor Forum
From KH@ATHENS.CS.WAIKATO.AC.NZ
Realname: Keith Hopper
To G_DOTZEL
Subject OO--------ps!
Date Fri, 04-30-93 at 04:54
Guenther,
I read your e-mail version of the OO proposal [The ModulaTor [3, 4], May-1993] just now
and I have a number of reservations which I thought I would share with you privately (just
in case I am wrong!!)
The separability of a class module definition from its implementation is not a problem
provided that the class module is itself a new pervasive type. By this I mean that
declaring
CLASS MODULE Widget ;
actually defines a new type directly accessible from the environment just like any other
pervasive type (which don't actually have 'visible' definition modules of course), the
name of the type being Widget. You may have seen the note I sent out yesterday to
Albert [Wiedemann] which discussed this(?) [replY: no, I didn't! The information channels
in the German WG13 subgroup are twisted roads] ). If you didn't, let me summarise it in
relation to your notes, since we have been asked to conduct technical discussion on a
one-to-one basis, rather than through the SC22WG13 list.
The purpose of the class module is to provide the abstract data type as a first-class entity
in the (extended) language. The beauty of this is that we merely need to extend the
notion of declaration semantics to encompass the initialisation code of the defining type
module implementation! The code for 'destruction' is likewise the finalisation code of that
module -- so that NEW and DISPOSE just contain the declaration semantics in the same
way. This is only a very minor change to the existing semantics -- with a major effect of
course.
This separability has the desired effect of retaining the 'flavour' of M-2.
The introduction of polymorphism is, I suggest, also essential at this outer level (rather
like the generic types in Ada). The matter is solved syntactically something after the style
of a module protection expression
CLASS MODULE AVL [Element] ;
where the identifier 'Element' is a formal type parameter. I have not thought through all
the implications of permitting multiple 'element' types, but I do not think it either
necessary or desirable.
Providing this kind of mechanism means that a polymorphic class type object declaration
could be sean as one of the following
TYPE
Filbert = RECORD
.
tree : POINTER TO AVL(CHAR) ;
.
END ;
VAR
Base_Tree
: AVL(REAL) ;
Egbert
: Filbert ;
.
.
.
WITH Egbert DO
.
NEW(tree) ;
.
END ;
.
in which Base_Tree is an AVL of REAL which had initialisation code executed at the
point when the declaration was elaborated -- Egbert.tree^ had its initialisation code
executed at the point of the call of NEW. This clearly avoids the need for another
'storage' module.
As an aside, I proposed also that the promotion of class module types in our language
extension led naturally to the thought that we should have the ability to provide
procedures which could be used in an infix manner in expressions -- so that a procedure
could be declared as, say,
INFIX PROCEDURE CONC(
Left : LIST
Right : Elem
) : LIST
and later used as
Queue := Queue CONC Entry
or something similar. Thinking this one through and adding a touch of knowledge of
Algol-68 enables us to contemplate defining the following
CLASS MODULE STRING ;
TYPE
Index_Range = RECORD
from,
up_to_and_including : CSRDINAL
END ;
INFIX (3) PROCEDURE "+"(
Left,
Right : STRING
) : STRING ;
INFIX (4) PROCEDURE "!"(
Target,
Pattern : STRING
) : STRING ; (* Tail after pattern - or empty *)
INFIX (2) PROCEDURE "<"(
First,
Second : STRING
) : BOOLEAN ;
INFIX (4) PROCEDURE "?"(
Range : Index_Range ;
Target : String
) : STRING ; (* Extracted sub-string! *)
etc.
END STRING.
in which the only new points are the specification of precedence and the use of string
identifiers -- purely for definition purposes -- which introduces the identifier over-loading
we have always wanted (I think!).
This could also lead to the addition of BCD (which I know the DIN group are very
interested in) in a similar fashion.
The one other matter about which I am unhappy in your own suggestion is the
'redefinition' problem. Here, again, I believe that there is a very simple elegant answer! At
present if an identifier is explicitly imported then it may not be redeclared. Contemplate,
however, the effect of an INHERIT clause whose semantics state that all identifiers
imported will be re-exported -unless- they are redefined. In this case the following could
happen for a module Garage, say, which had identifiers Fillup, Service, Wash and
Polish. A new class module could be defined thus
CLASS MODULE PitStop ;
FROM Vehicles IMPORT
CAR ;
INHERIT
Garage ;
PROCEDURE Service(
VAR Client : CAR
) ;
.
.
END PitStop.
in which case, assuming no other identifiers from Garage were redefined the original
Garage.Fillup, Garage.Wash and Garage.Service would be available as PitStop.Fillup,
etc (using the appropriate variable identifiers when using them of course -- eg
MODULE GrandPrix ;
IMPORT
Vehicles,
LIST, (* Another polymorphic/generic class! *)
STRING,
PitStop ;
TYPE
Racing_Cars = Vehicles.CAR ;
Entry = RECORD
vehicle : Racing_Cars ;
driver : STRING (* Just his/her name! *)
END ;
VAR
Entries
: LIST(Entry) ;
.
.
.
Stands,
Achterveld
: Pitstop ;
PROCEDURE Lap(
Field : LIST
) : LIST ;
VAR
Current
: Entry ;
.
.
BEGIN
.
.
Current := NEXT(Field) ;
IF ....... THEN
Stands.Service(Current)
END ;
.
.
IF ...... THEN
Achterveld.Service(Current)
END ;
.
.
END Lap ;
.
.
.
END GrandPrix ;
I hope that this also gives the flavour of the kind of programming that you attempted to
address without adding extra complication.
In short, whether or not you approve of my infix suggestions which would simplify
additional elementary type generation, I believe that the retention of separability (which
is a key matter in my estimation which I would not accept compromising) is eased as is
the use of the simple suggestions for inheritance (which -could- safely be multiple in my
opinion) and the easy expression of polymorphism in the class module heading.
In summary, we seem to agree on two of the additional tokens (CLASS and IS), have a
different understanding of what a module could be -- but I believe that my suggestion of a
class module being a type abstraction (as opposed to a state abstraction which is all we
have at the moment) has advantages, and similar feelings about the semantics involved.
Over to you! Feel free to pick at this, laugh at it (but please don't cry!) or pass it on to
others in the DIN group as you will.
Warmest regards,
Keith
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
![]()