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.