Mithril - Portable Oberon-2 System

                     A.Nedorya, A.Nikitin

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

The Introduction

The  essential part of any programming language realisation is
Language  Environment  (or Programming System). For the Object
Oriented  (OO)  language  such environment can be described as
the  set  of  absstract  classes  and concrete subclasses. The
Mithril  System  is  an  attempt  to construct the appropriate
environment  for  Oberon-2  language  [1].  The  system  is  a
development  of Oberon System [2]. As well as original one the
Mithril System is the single process multitasking system.

We  assume the Mithril System will be used as the base for the
portable   application   software   design.  To  simplify  the
application  software  design  it  is  necessary to solve some
important problems:

i)  the  creation of comfortable surroundings for a programmer
(languages, debugging and project support);

ii)  the  system  has to include the set of means for the user
interface creation (windows, mouse, interface constructor);

iii)  the  system  has  to  create  the  egual surroundings at
different  platforms  (i.e. at the different computers and the
different operating systems).

During   the   system   design  we  tryed  to  take  away  the
restrictions  of system extensibility by the accurate defining
of  the  base  type hierarchy, and to increase its portability
introducing the conception of driver.

The  possibility  of  (almost)  unlimited extensibility of the
system  is  the  main  property  that  differs  the Oberon and
Mithril  systems from usual programming systems. An extendable
system  consists  of  kernel which defines the set of the base
types  (the base for extension). Further the set of extensions
of  these  types.  Generally speaking, on each kernel numerous
sets  of  extensions can be constructed. From the programmer's
point  of view the extended types doesnot differ from the base
ones,  i.e.  in  the  extendable  systems  there is no barrier
between the system part and the user one.

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 on Oberon-2 language (the Oberon
System  is  implemented on Oberon). This language has a number
of  advantages  which allows one to improve the efficiency and
the extensibility of the system (in comparison with [2]):

a) the methods (type-bound procedures)
- permit  to  separate  accurately  the  operations  over each
  object  and  to  redefine  some  operations not changing the
  other one;
- increase  the  efficiency  by  taking  away  the superfluous
  dynamic checking of types;
- increase  the  reliability  thanks  to  the implicit methods
  initialization.

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

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

In  the  capacity  of auxiliary language when system designing
the 'oberonized' version of Modula-2 language was used.

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


1. User Interface

From user point of view the system does not differ practically
from  the Oberon System. After the system running user can see
at  the screen the window of standard output and the window of
system  tool  containing  the  set  of  the  base instructions
(including  the  instruction  of  new  window creation). Every
instruction 'M.P' consists of the module name 'M' and the name
of  the  procedure  without  parameters 'P'. The user runs the
instruction  by pressing of mouse key at the instruction text.
When  the  instruction  is  activated  the  system  calls  the
procedure  'P' of the module 'M' (loading the module 'M' if it
has not loaded yet).

In  contrast  to  the  Oberon  System  the system supports the
universal  multiwindows  interface.  The  accepted  in  Oberon
System division on 'tracks' is provided by proper heuristic of
window  placing at the screen. Such solution not only increase
freedom  of  window  accomodation  but  allows  one to work in
system on screens of small size.

In each time a lot of frames are situated at the screen. Every
frame  contains  the  management  handles  (for moving or size
changing)  and  some subwindows. The main subwindow is said to
be  working.  Since the conception of text and text windows is
very importent (all is text), then the base operations of text
edition are carried out by means of mouse keys (see [2]).


2. The System Structure

The  system  consists  of  three  parts:  the run time support
(RTS),  the  system  kernel  and  the  shell. Besides that the
system  includes the set of drivers to interact with operating
system and (or) hardware.

The  run time support (RTS) is an integral part of realization
of the Oberon-2 language. It includes the operations of memory
allocation,  garbage  collection  and objects finalization. In
our  system  RTS  is  implemented  on  Modula-2 language. When
porting  the system (**) RTS should be rewrited (as a rule) to
increase  the efficiency of garbage collection. It is used the
mark-and-sweep alhorithm [3] in garbage collection.

The system makes the garbage collection when any resource (not
obligatory   memory  resource)  is  insufficient.  Thus,  many
operating  systems  restricts  the  number  of  simultaneously
opened  files and the garbage collection can be run in time of
file  opening.  Every  object  can be registrated in RTS. Such
object  will be finalized (the finalizing procedure associated
with   it  will  be  made)  before  memory  deallocation.  The
finalizing  procedure  can  make necessary actions over object
(for example file closing).

The system kernel defines the set of base conceptions (types):
Object,  Persistent Object, Module, Rider, File, Font, Window,
Text.  Besides  that  it  realizes some useful libraries. When
system  running  (**)  the  system kernel makes the actions on
system configuration including drivers installation.

The   standard   system   shell   implements  minimal  set  of
conceptions  which  define the user interface (text windows in
the  first  turn) and the instruction set. The shell extension
can  be  made  by  two  ways:  the  instruction  set extension
(dynamic  extension)  and the extension of some base type (for
example, the extension of the window upto graphic window).


3. The Example of the System Extension

In   this  part  we  shall  try  to  show  the  technology  of
programming  in  the  system describing from top to bottom the
construction  of  so-called  'elements-instructions'. We shall
call   the   element   an   abstract   char   in   text.   The
element-instruction is the element extensions (**) upto active
element  which  executes associated with it operation when its
button is pressed. Naturally, we shall ommit a lot of details.
And  what  is more, a fair part of the system (files, modules,
loading)  will  not  be  considered  in this paper at all. All
examples will be adduced in some Oberon-like language, so, the
descriptions  of  methods  (type-bound procedures) will pesent
into   the  descriptions  of  corresponding  types.  We  shall
suppose,  that  works  [2,4]  are  wellknown  to  the readers,
otherwise the article should be divided into several volumes.

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

The  Text  in  system  is  symbol  sequence.  Each  symbol  is
associated with a set of attributes: font, colour and vertical
offset respectively to base line. The symbol attributes do not
depend of neighbour's attributes. All operations over the text
are  executed  over  char  sequence.  Each text can be seen by
numerous  ways  for different 'spectators'. Any operation over
the  text  involves  the  notification of all spectators about
changes in the text diapason.

The same way as in [2] the Text module defines base types Text
and  Buffer,  as  well as tyes Reader and Writer which realize
the   operations   of   access   to   the  texts  and  buffers
respectively.  Besides that, the conception of abstract char -
Element  [4]  -  is introduced. Numerous extensions of element
allow one to include pictures, drafts and other objects to the
text.   The   main   difference   of   this  module  from  the
corresponding  module  in the Oberon System is associated with
pass  to  the Oberon-2 language and usage of methods insist of
procedures,    what   essentially   increase   the   extension
possibilities.

From the descriptions of the Text module:

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  in  the  Text  module  are the
operations  which  were  used  in  it,  to  wit: copying of an
element  (copy) and sending of message to an element (handle).
The  'handle' method allows one to extend unrestrictly the set
of  operations  over  the  element.  The operations of element
drawing are defined in the Elements module (see below).

The  Element  is  an  extension  of  persistent  oject that is
defined in the Storage module.

From the module Storage descriptions:

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

    PROCEDURE (o: Object) constructor(): Str.String;
    (* returns the string containing the instruction 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  the  abstract  input/output
operations.


To realize the persistent objects there is used a scheme which
units  methods  described  in  [4,5]. When object writing (**)
first  the  string-constructor  is  written,  then  the method
'externalize'  is called to write an object state. When object
reading  (**) first the string-constructor is read, after that
it is executed and, if the creation was successful, the object
state is restored by call of method 'internalize'.

During  text  reading  realization it's necessary to take into
account the situation, when the element cannot be read because
of  failure  in loading of the module realized this method. In
this  case  the  'unknown' element is created, which saves the
information about the source element.

In   one's   turn   the  Storage.Object  is  an  extension  of
Objects.Object,  which  defines  the  root  type  in  the type
system.

Now  let us pass to the windows. The implementation of windows
in  the  system is considered in details in [6]; in this paper
we'll list briefly the main properties of window subsystem.

Any new window is created on base of some window-parent. First
in  the  Window  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  Screen.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 windows-screen 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 extended during
its  work.  The level of screen driver allows one to take away
all  dependence  on concrete hardware out of the system and to
improve essentially its portability.

The  Windows  module  defines  the  abstract window conception
which  can  be  extended  for  drawing  of objects of numerous
structures. The text window extends the abstract window adding
the  operations of text drawing and editing. All operations of
edition  of  window  contents  are implemented as in [2]. Each
operation  includes  copying  and removing of some part of the
text,  chaanging  of char attributes, cursor set, vertical and
horisontal  positing  (**)  in text. The other operations over
the text are implemented as an instruction set.

The  implemented  text  windows  are  in  the middle situation
between  the  text  windows described in [2] and [4]. From the
one  side  the  text  windows  can execute the operations over
abstract  char  (element), from the other one we hold that the
the  formatting operations (see [4]) must be implemented above
the text windows level.

To draw elements in text windows it is necessary to extend the
Text.Elem  type  by  the  operations  of element drawing. Such
extension is described in the module Elements.

From the descriptions of the Elements module:

TYPE
  Elem = POINTER TO ElemDesc;
  ElemDesc = RECORD (Texts.ElemDesc)
    w*,h*: INTEGER;   (* linear size 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;

At    last    let    us   consider   the   implementation   of
elements-instructions.  For  the  beginning  let us extend the
abstract  element  (Elements.Elem) by 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 of
drawing and copying as well as element storing/restoring.. Now
we'll list the schemes of some methods implementation.

PROCEDURE (e: Icon) 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: Icon) copy(VAR x: Texts.Elem);
  VAR i: Icon;
BEGIN
  IF x=NIL THEN NEW(i); x:=i END;
  e.copy^(x);      (* superclass method call *)
  WITH x: Icon DO  (* verification of the dynamic type x *)
    x.icons:=e.icons;
    x.no:=e.no;
  END;
END copy;

The  Icon  type  is  extending  by  adding  of instruction and
possibility of its run.

TYPE
  CmdElem = POINTER TO CmdElemDesc;
  CmdElemDesc = RECORD (IconElemDesc)
    icon: BOOLEAN;      (* icon state *)
    cmd : Str.String;   (* instruction *)
  END;

We   must   redefine   the  operations  of  drawing,  copying,
storing/restoring and the reaction on mouse button click.

PROCEDURE (c: CmdIcon) handle_mouse(v: wnd.Window; x,y: INTEGER;
                                    keys: SET);
BEGIN
  IF middle_button IN keys THEN
    (* суммируем кнопки мыши, пока все они не будут отжаты *)
    IF keys={middle_button} THEN
      (* only the middle button was pressed *)
      Kernel.call(c.cmd^,....);    (* instruction call *)
    ELSIF right_button IN keys 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, in another one - as an framed
instruction text.

PROCEDURE flip(c: CmdIcon);
BEGIN
  c.icon:=NOT c.icon;
  Texts.notify_elem(c);
END flip;

The  'Texts.notify_elem'  procedure  informs  all 'spectators'
(usually  they are the text windows) about changing of element
state.

PROCEDURE (c: CmdIcon) 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 instruction text *)
  END;
END draw;

We  need  just to implement the instruction which will put the
element-instruction to an arbitrary text.

PROCEDURE InsCmd*;
  VAR v: TextWindows.Window;  c: CmdIcon;
      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;

Now    it    is   satisfitient   to   type   the   instruction
IconElems.InsCmd  to  insert  the  element-instruction  to  an
arbitrary text.

During  the  example implementation we've obtained long enough
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 instruction

Each  level in this hierarchy has a sence, i.e., the first, it
has exact defined semantic and, the second, it can be extended
by numerous ways.

Note,  that  the elements-instructions implemented in this way
are used in the system for user interface forming.

4. Conclusion

The  Object  Oriented  systems  design  is,  perhaps, the most
fashionable  kind  of activities in the world during some last
years.  The  Mithril system features from an analogous systems
with some very important aspects:

        1) the (**)

    1)  минимальность  и ортогональность системы

(the  base  level  of  the  system  implements  only necessary
notions set);

2)  strict  hierarchy  of  base  types  (the  majority of such
systems  is  designed with using of multiple inheritance, what
leads  to  badly  structured  type  system  and  decrease  the
ppossibility of extension);

3) the independence on hardware and operating system.

The  main  failure  of  the  system,  the  absence of parallel
process  support,  is  consequence of choise of implementation
model.  In  the  next versions of the system we'll try to take
off this restriction.

Let us list briefly some important conclusions which have came
in time of the system designing.

In  time  of such system designing the important factor is the
properties   of  programming  language:  extension  of  types,
dynamic  typization  (**),  garbage collection. The absence of
dynamic typization in C++ language makes problematic its usage
in  design of powerful object-oriented systems. There does not
raise a necessivity in multiple inheritans if system design is
fulfilled accurately.

The  pass  from the Oberon language to thr Oberon-2 allows one
th  increase  the  system extensibility and simultaneously its
efficiency.

The  driver  conception  is  very  important  for  the  system
portability.  All  parts  depending on hardware and system are
put into driver, after what one can port the system.

Powerful  window subsistem takes away all restrictions of work
with  windows  and permits to form the system interface by the
arbitrary way.

And,  at  last, we want to thanks to all who helped us in this
work and GREAT thanks to all who didn't preven us.


REFERENCES

1. H.Mossenboeck, N.Wirth
   The Programming Language Oberon-2
   Structured Programming (1991) 12: 179-195

2. J.Gutknecht
   The Oberon Guide: System Release 1.2
   Report 138, ETH Zurich, 1990.

3. B.Heeb, C.Pfister
   An Integrated Heap Allocator/Garbage Collector
   In report 157, ETH Zurich, 1991.

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

5. J.Templ,
   A Symmetric Solution to the Load/Store problem
   In report 157, ETH Zurich, 1991.

6. A.Nedorya, A.Nikitin,
   The window support in the Mithril System.