The ModulaTor logo 7KB

The ModulaTor

Oberon-2 and Modula-2 Technical Publication

Erlangen's First Independent Modula_2 Journal! Nr. 6/Jul-1992


Mithril - A Portable Oberon-2 System

by A.Nedorya, A.Nikitin, IIS, Novosibirsk, Russia

"Mithril! All folk desired it." The Lord of the Rings J.R.R. Tolkien

Introduction

The language environment is an essential part of any language. For an object-oriented language such an environment can be described as a set of abstract classes and concret subclasses. The Mithril system is an atempt to build appropriate environment for the Oberon-2 language [MoWi91]. We assume the system will be used as the base for the design of portable application software.

The Mithril system is a descendent of the Oberon System [Gu90]. As the original system Mithril is a single process, multi-tasking system. The main aims of the new system design was to take off the system extensibility limits and to improve its portabilty. The new features of Oberon-2 (type-bound procedures, read-only export and dynamic arrays) helped us to achieve these goals.

The possibility of (almost) unlimited extensibility of the system is the main property where the Oberon and the Mithril Systems differ from usual programming systems. An extendable system consists of a kernel which defines the set of the base types (the base for extension). Further the set of extensions of these types can be defined. The extended types do not differ from the base type, i.e. in the extendable systems there is no barrier between the system part and the user part. Generally speaking, numerous sets of extensions can be constructed on the kernel.

The construction of reliable extendable systems is impossible without proper language support. In the first place the language must support the notion of type extension. The Mithril System is implemented in the Oberon-2, while the Oberon System is implemented in Oberon. The language Oberon-2 has a number of advantages which allows one to improve the efficiency and the extensibility of the system (in comparison with [Gu90]):

a) methods (type-bound procedures)

b) read only export permit to increase the efficiency of access to the object attributes, without any loss of reliability.

c) dynamic arrays permit to increase the universality of the operations and avoid restrictios in the system.

When designing the system, we used an oberonized version of Modula-2 as auxiliary language.

Further in the paper we'll describe the user interface of the system, its structure and we'll also analyse an example which shows the possibilities of system extension.

1. User Interface

From the user point of view the system does not differ practically from the Oberon System. After system startup user can see at the screen the standard output window and the system tool's window containing the set of the base commands (including the command for the creation of a new window). Every command M.P consists of the module name M and the name of the parameterless procedure P. The user activates a command by clicking a mouse key at the command place. When the command is activated the system calls the procedure P of the module M (by implicitely loading the module M if it has not yet been loaded).

In contrast to the Oberon System, Mithril supports the universal multi-windows interface. This solution not only increases the freedom of window placement but also allows one to use smaller-sized screens. The so-called screen division into tracks of the Oberon System's are provided by proper window placing heuristics.

Most of the time many windows are situated at the screen. Every window contains the management handles (for moving or resizing) and some subwindows. Since the concept of text and text windows is very important, the base operations of text editing are carried out by means of the mouse keys (see [Gu90]).

2. The System Structure

The Mithril System consists of three main components: run time support (RTS), system kernel and environment. Furthermore there is a set of drivers which interact with the underlying operating system and (or) hardware.

The run time support (RTS) is an integral part of the Oberon-2 language implementation. It includes memory allocation, garbage collection and object finalization. In our system RTS is implemented in Modula-2. When porting the system RTS should be rewritten (as a rule of thumb) to increase the efficiency of garbage collection. The mark-and-sweep algorithm [HePf91] is used for garbage collection.

The system activates the garbage collector when any resource which is not an obligatory memory resource, is insufficient. For example, many operating systems restrict the number of simultaneously opened files and the garbage collection can be run when opening files. Every object can be registrated in the RTS. Such objects will be finalized (ie.: the finalizing procedure associated with it will be called) before memory is deallocatated. The finalizing procedure performs the required actions on the object, such as file closing.

The system kernel defines the set of base concepts (types): Object, Persistent Object, Module, Rider, File, Font, Window, Text. Furthermore it contains some useful libraries. During system startup the kernel is responsible for system configuration including drivers installation.

The standard environment implements a minimal set of concepts which define the user interface (text windows in the first turn) and the command set. The environment extension can be made by two ways: by command set extension (dynamic extension) and by extenting some base type (for example, the extension from window to graphics window).

3. An Example of the System Extension

In this part we shall try to show the methotology of systems programming by describing the construction of so-called element-commands from top to bottom. The example doesn't go into detail. Also, the other parts of the system (files, modules, loader) will not be considered in this paper. The notation used in the examples is a language similar to Oberon. The difference is that the definition of methods (type-bound procedures) is presented within the definition of the associated record types. To keep the paper short, we refer to the articles [Gu90,Sz91] for further details.

We call the element an abstract character in text. The element-command is the extension of element which executes the associated command when activated.

First let us define the Text concept and consider its structure; then we shall pass to windows, and then - to text windows.

The Text in system is a sequence of characters. A set of attributes is associated with a character: font, color and vertical offset from the base line. The character attributes do not depend on neighbour's attributes. A text can be seen by numerous ways by different viewers. An operation on text involves the notification of all viewers about changes in the text range.

As shown in [Gu90], the Texts module defines the base types Text and Buffer, as well as types Reader and Writer which implement an access to texts and buffers. Besides that, the concept of abstract character - element [Sz91] - is introduced. Numerous extensions of element allow one to include pictures, drafts and other objects into the text. The main difference of this module from the corresponding module in the Oberon System is that some new features of the Oberon-2 language are used (type-bound procedures).

Module Texts


  TYPE
    Elem = POINTER TO ElemDesc;
    ElemDesc = RECORD (Storage.ObjectDesc)
      temp*: BOOLEAN;     (* suppress storage of element *)
      ....
      PROCEDURE (e: Elem) copy(VAR x: Elem);
      PROCEDURE (e: Elem) handle(VAR M: Objects.Message);
    END;

  PROCEDURE broadcast(T: Text; pos,end: LONGINT; VAR M: Objects.Message);
  (* send a message to all elements within stretch [beg..end[ *)
The only operations defined for element in the module Texts are the operations which are needed by the module itself: copy an element (copy) and send a message to an element (handle). The handle method allows one to unrestricted extend the set of operations over element. The operations for element drawing are defined in the module Elements (see below).

An element is an extension of the persistent object that is defined in the module Storage.

Module Storage


  TYPE
    Object = POINTER TO ObjectDesc;
    ObjectDesc = RECORD (Objects.ObjectDesc)

      PROCEDURE (o: Object) constructor(): Str.String;
      (* returns the string containing the command of object
         creation; Str.String = POINTER TO ARRAY OF CHAR.
      *)

      PROCEDURE (o: Object) externalize(r: Riders.Rider);
      (* writes the object state *)

      PROCEDURE (o: Object) internalize(r: Riders.Rider);
      (* restores the object state *)
    END;
The Riders.Rider type defines abstract data type for input/output operations.

Persistent objects are implemented according to [Sz91,Te91]. To store an object the header of an object is written and then the method externalize is called to write an object state. The header contains a command for object allocation (constructor). To load an object the command-constructor is read, after that it is executed and, if an object was successfuly created, the object state is restored by call of internalize method.

To load text it is necessary to take into account the situation, when the element cannot be read because of failure in loading of the module containing command-constructor. In this case a special unknown element is created, which saves the information about the source element.

Storage.Object is an extension of Objects.Object, which defines the root type in the type system.

Module Windows

The implementation of windows in the system is considered in details in [NiNe92]; this paper only shows the main properties of window subsystem.

Any new window is created on base of some window-parent. First in the Windows module the only window - meta-desktop - is defined. The windows corresponding to the physical screens - desktops - are created on the meta-desktop. The system supplies the multiscreen regime, i.e. it can work simultaneously at several physical screens. For each physical screen the screen driver must be defined. The Screens module defines the type Screen - an abstract screen driver. The concrete screen driver extends Screens.Screen. A screen driver defines screen characteristics: size in pixels, a number of layers, a palette, e.t.c. and implements a collection of graphic primitives. The system places all window-screens to single line (the ordinate of the left corner of each screen equals to 0). The sizes of screens can be different. The next screen can be added on the left or on the right from the screens set before.

The set of window-screens and their placement are defined during the system initialization and can be modified when desired. The level of the screen driver allows to remove all system hardware dependencies and to essentially improve its portability.

The Windows module defines the abstract window concept which can be extended for drawing objects of various structures. The text window extends the abstract window adding operations for text drawing and editing. All editing operations within windows are implemented as in [Gu90]. The set of operations includes copying and removing some part of the text, changing of character attributes, cursor placement, vertical and horizontal text positionning. The other operations on text are implemented as commands.

To draw elements in text windows it is necessary to extend the type Texts.Elem by the operations needed for element drawing as defined in module Elements.

Module Elements

  TYPE
    Elem = POINTER TO ElemDesc;
    ElemDesc = RECORD (Texts.ElemDesc)
      w*, h*: INTEGER;   (* linear sizes of element *)

      PROCEDURE (e: Elem) prepare(v: Windows.Window;
                        font: Fonts.Font; col: SET; voff: INTEGER);
      (* the prearation of the element for drawing;
         the element's size can be changed.
      *)

      PROCEDURE (e: Elem) draw(v: Windows.Window; x,y: INTEGER;
                        font: Fonts.Font; col: SET; voff: INTEGER);
      (* element drawing *)

      PROCEDURE (e: Elem) handle_mouse(v: Windows.Window;
                                     x,y: INTEGER; keys: SET);
      (* cursor management for the element *)
    END;
The implementation of element-commands

First the abstract element (Elements.Elem) is extended to support the drawing of some icon. We assume that the icon images are stored in the some font.


  TYPE
    IconElem = POINTER TO IconElemDesc;
    IconElemDesc = RECORD (Elements.Elem)
      icons: Fonts.Font;  (* font with icons *)
      no   : SHORTINT;    (* the icon number in the font *)
    END;
To implement such elements we need to define the operations for drawing and copying as well as element storing/restoring. Here are some excerpts from the implementation of the associated methods.

  PROCEDURE (e: IconElem) draw(v: Windows.Window; x,y: INTEGER;
                           f: Fonts.Font; color: SET;
  BEGIN
    ...
    Windows.writech(v,..,f,x,y,e.no);   (* icon drawing *)
    ...
  END draw;

  PROCEDURE (e: IconElem) copy(VAR x: Texts.Elem);
    VAR i: IconElem;
  BEGIN
    IF x=NIL THEN NEW(i); x:=i END;
    e.copy^(x);      (* superclass method call *)
    WITH x: IconElem DO
      x.icons:=e.icons;
      x.no:=e.no;
    END;
  END copy;
The type IconElem is extended by adding the text of a command and an operation for command activation.

  TYPE
    CmdElem = POINTER TO CmdElemDesc;
    CmdElemDesc = RECORD (IconElemDesc)
      icon: BOOLEAN;      (* icon state *)
      cmd : Str.String;   (* command *)
    END;
We must redefine the operations for drawing, copying, storing/restoring and the reaction to clicking a mouse button.

  PROCEDURE (c: CmdElem) handle_mouse(v: wnd.Window; x,y: INTEGER;
                                      keys: SET);
  BEGIN
    IF middle_button IN keys THEN
      sum:=keys;
      LOOP
        Kernel.mouse(x,y,keys);
        IF keys={} THEN EXIT END;
        sum:=sum+keys;
      END;
      IF sum={middle_button} THEN
        (* only the middle button was pressed *)
        Kernel.call(c.cmd^,....);    (* command call *)
      ELSIF right_button IN sum THEN
        (* the right and the middle button was pressed *)
        flip(c);  (* change the element state *)
      ....
      END;
    END;
  END handle_mouse;
The procedure flip switches the element state. In one state the element is drawn as an icon, otherwise as a framed command text.

  PROCEDURE flip(c: CmdElem);
  BEGIN
    c.icon:=NOT c.icon;
    Texts.notify_elem(c);
  END flip;
The Texts.notify_elem procedure informs all viewers (usually these are text windows) about the change of an element state.

  PROCEDURE (c: CmdElem) draw(v: Windows.Window; x,y: INTEGER;
                           f: Fonts.Font; color: SET;
  BEGIN
    IF c.icon THEN
      c.draw^(v,x,y,f,color);  (* draw the icon *)
    ELSE
      .....
      Windows.frame( .... );       (* draw the frame *)
      Windows.print(....,c.cmd^);  (* draw the command text *)
    END;
  END draw;
Now we need to implement the command which will insert the element-command into an arbitrary text.

  PROCEDURE InsCmd*;
    VAR v: TextWindows.Window;  c: CmdElem;
        w: Texts.Writer;        f: Fonts.Font;    no: SHORTINT;
      cmd: Str.String;
  BEGIN
    ....
    v:=focus_window();  (* the window containing the text cursor *)
    get_parameters(f,no,cmd);
    c:=command(f,no,cmd); (* create the element *)
    w.element(c);         (* add the element to the buffer w.buf *)
    v.text.insert(v.carloc.pos,w.buf);
    (* insert the element to the cursor position *)
  END InsCmd;
During the example implementation we have obtained the following type hierarchy:

  Objects.Object                       root type in the type system
  Storage.Object                       persistent object
  Texts.Elem                           persistent element
  Elements.Elem                        drawing persistent element
  IconElem                             element-icon
  CmdElem                              element-icon with command
Each level in this hierarchy provides a certain level of abstraction, from the first, which has exactly defined semantics and the second which can be extended in various ways.

Note, that the element-commands implemented in this way are used in the system to form the user interface.

4. Conclusion

Object oriented systems design is perhaps the most attractive and challenging kind of activities in the world. We hope this paper helped to illustrate some of the advantages of the Mithril system helped. Let us briefly list its most important features.

The right choice of an appropriate programming language is very important factor for extensible system design.

There is no need for multiple inheritance when the system is designed accurately.

The step from the Oberon language to Oberon-2 helped us to increase both, the system's extensibility and efficiency.

The driver concept is very important for the system portability. All parts that depend on the hardware system are put into drivers.

The powerful window subsystem takes away all restrictions of working with windows and permits to form the system's interface in a flexible way.

The main disatvantage the system is the absence of parallel process support, which is the consequence of the underlying dynamic model. In the next versions of the system we'll try to overcome this restriction.

And, at last, we want to thank all who helped us in this work and GREAT thanks to all who did not prevent us.

References

[MoWi91] H. Moessenboeck, N. Wirth: The Programming Language Oberon-2, in Structured Programming (1991) 12: 179-195

[Gu90] J. Gutknecht: The Oberon Guide - System Release 1.2, Report 138, ETH Zurich, 1990.

[HePf91] B. Heeb, C. Pfister: An Integrated Heap Allocator/Garbage Collector, Report 157, ETH Zurich, 1991.

[Sz91] C. Szyperski: Write: An Extensible Text Editor for the Oberon System, Report 151, ETH Zurich, 1991.

[Te91] J. Templ: A Symmetric Solution to the Load/Store problem, Report 157, ETH Zurich, 1991.

[NiNe92] A. Nikitin, A. Nedorya: The window support in the Mithril System, Report N, ISI Novosibirsk, 1992

Received from ned@isi.itfs.nsk.su (now ned@xds.ru) in 19 Jun 1992.


DEC WRL Modula-2 Announcement

[from Usenet comp.lang.modula2]

The Western Research Laboratory of Digital Equipment Corporation is pleased to announce the availability of a new version of their Modula-2 compiler for VAXes running Ultrix or BSD, and for MIPS-based DECstations running Ultrix.

New in this release are support for the following modules described in Wirth's book: InOut, MathLib0, RealInOut, Terminal, and TextIO. These were contributed by Philip A. Nelson. And the MIPS compiler has been brought up to date with the VAX compiler, so the two compilers now accept the same language. [editors note: WRL Modula-2 has many language extensions; none of these are ISO Modula-2 compliant. WRL Modula-2 includes many library modules; although there is also an ISO Modula-2 module called TextIO, none of the WRL conform to any module of the ISO Modula-2 Standard Library.]

The compiler was designed and built by Michael L. Powell, and originally released in 1984. Joel McCormack sped the compiler up, fixed lots of bugs, and swiped/wrote a User's Manual. Len Lattanzi ported the compiler to the MIPS.

The compiler generates better code than most compilers for the VAX. The error messages are quite a bit better than those from the Ultrix C compiler and the compile time is about the same as cc and gcc. Further, the compiler includes an intermodule checker that uses fine-grained dependencies rather than timestamps, so you can modify definition modules in upward-compatible ways without recompiling the world.

The compiler includes several extensions. The most notable are: provisions for interfacing with procedures and data types written in other languages like C and Pascal (a definition module for the X11 C library is included); dynamic array variables, subarray parameters, and multi-dimensional open array parameters; inline procedures; complete support for the LONGFLOAT type; and a pseudo-module providing a type-checked interface to the C library I/O routines.

The VAX portion of the release includes a Pascal compiler that accepts a language almost identical to Berkeley Pascal. (Procedure parameters are not supported, and record layout and parameter passing conventions are somewhat different.) The VAX portion of the release also includes a program that does most of the translation of Berkeley Pascal programs into Modula-2.

The compiler is available for anonymous ftp from gatekeeper.dec.com, in the 5.6 megabyte compressed tar file /pub/DEC/Modula-2/m2.tar.Z. Once you have copied this file into a directory called m2, you can uncompress it and untar it, like:

uncompress m2.tar.Z

tar xf m2.tar

This will create two additional directories, m2-vax and m2mips, at the same level in the directory hierarchy as m2. (The uncompressed tar file is about 13.6 megabytes, and the untarred files will take up about 13.7 megabytes, so make sure you have a lot of disk space.)

From there, read the README file, and the m2vax/doc/installation.f file.

The compiler is available to DEC sites over DECNET at decwrl::/pub/DEC/Modula-2/m2.tar.Z.

The compiler is also available by magnetic tape. Please specify whether you would like a 9-track, 1600 bpi tape, or a TK50 tape. Send a check made out to Digital Equipment Corporation for $100 US to:


        Director of Licensing
        Digital Equipment Corporation
        Western Research Laboratory
        250 University Avenue
        Palo Alto, CA  94301
Unlike the previous license, the new license does not restrict use of the compiler to educational institutions. The license agreement is as follows:


Copyright 1984-1992 Digital Equipment Corporation
All Rights Reserved

Permission to use, copy, and modify this software and its documentation is hereby granted only under the following terms and conditions. Both the above copyright notice and this permission notice must appear in all copies of the software, derivative works or modified versions, and any portions thereof, and both notices must appear in supporting documentation.

Users of this software agree to the terms and conditions set forth herein, and hereby grant back to Digital a nonexclusive, unrestricted, royalty-free right and license under any changes, enhancements or extensions made to the core functions of the software, including but not limited to those affording compatibility with other hardware or software environments, but excluding applications which incorporate this software. Users further agree to use their best efforts to return to Digital any such changes, enhancements or extensions that they make and inform Digital of noteworthy uses of this software. Correspondence should be provided to Digital at:

Director of Licensing Western Research Laboratory Digital Equipment Corporation 250 University Avenue Palo Alto, California 94301

This software may be distributed (but not offered for sale or transferred for compensation) to third parties, provided such third parties agree to abide by the terms and conditions of this notice.

THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


If you have any questions, you can send mail to

        decwrl!modula-2
or
        modula-2@decwrl.pa.dec.com
or
        decwrl::modula-2
This compiler has a number of internal and external users and we feel it is quite reliable. However, new users often find new bugs so we expect to hear from some of those who try it. No promises about bug fixes or new releases, though.

The ModulaTor Forum

[editors note: I've asked Joel whether a VMS version of WRL Modula-2 is also available and what language differences and extensions he made]

Guenter,

Nothing available on VMS. Otherwise, availability is still as I announced. [editors note: see announcement above]

I am currently working on making the MIPS sources available.

The language is roughly Modula-2, open to various interpretations due to ambiguities in the Wirth revisions. I haven't even looked at the ISO extensions and libraries. Since the sources are provided, someone could do this work, but I'm pretty much not interested in the Modula-2 compiler myself any more.

The User Manual, included in PostScript form in the distribution, contains more details.

There are lots of hooks in there for VMS. There is a VMS version that people use internally. I don't use VMS. I have never spent the time to package up the VMS version. I doubt that I will, at this point. It isn't really worth my time. [ed. note: WRL Modula-2 generates symbolic assembly code]

[asked what differences are between Modula-2+ and WRL Modula-2:]

This compiler does not accept the Modula-2+ language. People over at SRC did that, based on a very old version of this compiler. They may have been distributing their compiler for awhile, I don't know. The whole lab there is dumping Modula-2+ and moving onto Modula-3, a much better language. Modula-2+ was a hack, Modula-3 is really pretty elegant.

It is largely the same compiler described in an early [ACM] SIGPLAN article.

[asked why the new release of WRL Modula-2 is still not in the ISO Modula-2 direction:]

Wirth's book doesn't describe ISO Modula-2, nor any modules from ISO Modula-2.

And for most of the Modula-2 world, ISO Modula-2 is not an issue. It's taken forever for a bunch of people to argue about all sorts of things, and in the meantime the world has passed them by!

I got piles and piles of papers from the working group. I got tired of reading them. Too many people trying to stick their pet extension in.

[and finally asked for his age:]

I'm 34. I used to run Volition Systems. We started selling Modula-2 compilers [ed. note: for the Apple II] back in 1982, I believe. I just maintain the WRL Modula-2 compiler as a public service. If I were to start any big new project, I'd want to use Modula-3, even though the runtime is far too large.

Go ahead and quote me.

Joel McCormack

Received 02 May 1992 from joel@pa.dec.com


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 Günter Dotzel; he can be reached at mailto:[email deleted due to spam]


Home | Site_index | Legal | OpenVMS_compiler | Alpha_Oberon_System | ModulaTor | Bibliography | Oberon[-2]_links | Modula-2_links |

Revised 16-Dec-1998; screen shots (generated under Linux running Mithril in dosbox) added in 20-Jun-2012.