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.