Home‎ > ‎Computing‎ > ‎Byte Articles‎ > ‎

The Oberon System (1992)

Dick Pountain - 14/12/92 12:37 - BYTE


                         THE OBERON SYSTEM

Professor Niklaus Wirth is known far beyond the borders of his native 
Switzerland, as the designer of the Pascal and Modula-2 languages. 
Oberon, his latest language, is not yet in widespread use though there 
are a number of public-domain compilers in circulation. Oberon is more 
than just a language; it's one part of a research project which 
comprises an engineering workstation, its operating system and the 
compiler. What's more the Oberon operating system is a radically 
object-oriented design that prefigures many of the features that will 
be seen in our next-generation PC operating systems.

Whether it's IBM and Apple's Taligent, Microsoft's 'Cairo' version of 
Windows, GO Corporation's Penpoint or Apple's Newton OS, there is sure 
to be an object-oriented operating system somewhere in your future. At 
the moment few computer users have much idea of what a truly 
object-oriented operating system will look like, or just how much it 
will alter our concepts of computer software. A recent encounter with 
the Oberon system has given me a much better idea of what to expect, 
and I'm impressed. Under Oberon the notion of an application program 
completely disappears in favor of groups of small programs called 
tools. The operating system understands fundamental data types like 
structured texts and pictures, and 'applications' are just customized 
viewers for these types that add new functions.


SOME BACKGROUND

Starting in 1985, Wirth and his fellow professor Jurg Gutknecht at ETH 
(the Eidgenossische Technische Hochschule in Zurich) designed the 
Oberon language and operating system in parallel with development of 
their Ceres workstation project. Ceres and Oberon became a test-bed 
for Wirth's philosophy of achieving reliability through simplicity -- 
he's fond of quoting Albert Einstein's famous epigram "Make it as 
simple as possible but not simpler". In his book on the Oberon system 
Wirth argues forcefully that modern software (both system and 
application) has become grossly overweight and inefficient, and that 
consequently the semiconductor industry's continual improvements in 
memory size and processor speed are being squandered for minimal 
performance gains. Software development lags behind hardware, 
progressing by a fossil-like process of accretion in which extra 
layers of code are grafted on to adapt obsolete systems. Wirth's 
argument is not primarily economic, for memory and CPU power are 
indeed becoming cheap commodities -- his objection to inflated size is 
that it brings with it unreliability. The probability of introducing 
bugs increases explosively with program size, so smaller systems are 
also likely to be more reliable systems. Any unbiassed observer of 
current systems (Unix, Windows, OS/2) must find it hard to disagree 
with his verdict.

Wirth's prescription for fighting the flab is EXTENSIBILITY -- the 
ability to add to a system by extending its existing capabilities, 
rather than continually duplicating them. For example it's wasteful to 
incorporate new text-editing code into every application, when all 
could share a centrally provided basic editor and customize it for 
particular purposes. To write an extensible system you need an 
extensible language which allows you to add modules that reuse the 
built-in data structures without forcing you to recompile the whole 
operating system. The Oberon language resembles a stripped-down 
Modula-2 with the added ability to extend data types, so that new data 
types can inherit features from existing ones. Oberon programmers 
write in object-oriented style by installing special procedures called 
'handlers' that bind methods to data objects at run-time. The latest 
version, Oberon-2, is fully object-oriented with explicit binding of 
methods to types. [The Oberon language was more fully described in 
Byte, March 1991, page 135.]

The ETH researchers started with a completely clean slate in both 
hardware and software, unencumbered by any requirements for backward 
compatibility, industry standards or commercial acceptability. Ceres 
(now into its third generation, Ceres-3) is a single-board graphical 
workstation driven by a National Semiconductor NS32GX32 CPU. It's 
features include a 1024 x 800 color screen, three button mouse, 4 to 8 
Mbytes of memory and a simple serial network interface based on RS485. 
Over 100 Ceres are used daily by students and staff in ETH labs.

ETH now has public-domain versions of the Oberon operating system and 
compiler for other platforms including IBM PC and Apple Macintosh (see 
end of article). Each port took around 6 man-months, which suggests 
that the philosophy is working -- the PC version occupies just 1.5 
Mbytes of hard disk space including the source code.


THE OBERON USER INTERFACE

It's almost impossible to explain the Oberon system without 
considering its user interface first. Oberon employs a GUI with 
built-in support for fonts and bitmaps, but with tiled rather than 
overlapping windows. Wirth and Gutknecht reject the overlapping 
windows metaphor as too much complication for a small advantage -- 
though I suspect that this is an argument they have already lost to 
millions of Mac and Windows users. Programmers can easily produce 
overlapping windows as an extension.

The Oberon screen is split vertically into two 'tracks' each 
containing several non-overlapping panes called 'viewers' stacked one 
above the other. The wider lefthand track is the 'user track' where 
program output appears, while the narrower righthand 'system track' is 
used for system messages and commands. You can type text into any 
viewer by setting the caret cursor in it with a mouse click.

Everything in Oberon happens within viewers, so there is no main menu 
bar at the top of the screen (see fig.1). Each viewer has three parts: 
a main area for text and pictures; a vertical scroll bar; and a 
reverse-video bar that holds the viewer's title and a list of commands 
that looks like a horizontal menu. I deliberately said 'looks like' 
because the Oberon system is completely modeless and so strictly 
speaking has no concept of a menu -- all text that appears on an 
Oberon screen is treated in exactly the same way and is always 
editable. A disk directory listing, the commands in the title bar, 
even system messages are all editable (and maybe executable) text. 

You can execute any text string which names a valid Oberon command by 
pointing and clicking the middle mouse button, no matter where it 
appears on the screen. Oberon commands are always of the form 
<module>.<command> (eg. Edit.Copy, Draw.Erase) and are simply the 
qualified names of procedures exported from an Oberon module. When you 
compile your own Oberon modules, your new procedures immediately 
become available as commands.

You tend to work in Oberon by setting up small scratchpad viewers in 
the system track which hold the names of all the commands you are 
currently working with; these viewers are in effect user-defined menus 
and you need never type any command's name more than once. You may not 
need to type it at all since you can load texts called 'tools' from 
disk, that list all the commands exported by a particular module. Some 
of the tools provided with Oberon are System, Edit, Draw, Paint and 
Write, and Compiler. The Edit tool provides just the most basic 
editing functions (like the Mac or Windows Notepad editor) of cutting, 
copying and pasting with the mouse, but the Write tool (an extension 
of Edit) is a full document editor with fonts and formatting. 
Executing any one of a tool's commands causes the operating system to 
load the corresponding module if it's not already in memory; there is 
no explicit program loading in Oberon.

Most Oberon commands take their operands from the screen. For example 
you might select a stretch of text with the mouse and then execute the 
Edit.Copy command on that selection. To make a whole viewer the input 
for a command you mark it by placing the cursor in it and pressing the 
mark key. You can apply any tool to any viewer, and to the output of 
any previous command. For example I might list a disk directory (by 
clicking System.Directory), then select a file name from the newly 
opened Directory viewer and click Write.Open to edit that file in a 
new Write viewer. 

You can run the compiler on any viewer that contains Oberon source, 
compile into memory and then run the new commands; it's very like the 
Turbo Pascal environment, with compilation so fast that it feels like 
an interpreter. I found the whole Oberon system very fast and 
convenient once I'd mastered the initially daunting mouse button 
combinations, and no, I didn't miss having to push overlapping windows 
around. 

THE STRUCTURE OF OBERON

The Oberon system offers a very different model of computer/user 
interaction from that offered by, say, Unix, MS-DOS or Windows. For 
example it has no concept of a 'program' comparable to a .EXE file. 
Oberon's unit of action is a single procedure call, or command, while 
the unit of compilation is a module which may export several commands. 
Commands must be parameterless procedures, and they receive their 
run-time arguments (such as screen selections) via a system variable 
called Oberon.Par.

Commands are atomic actions which cannot be interrupted before 
completion (except by the abort key). This means that Oberon commands 
can't interact with the user, which is why you always specify a target 
BEFORE executing the command -- there are no dialogs in Oberon, and 
very few input statements. Consecutive Oberon commands normally swap 
data via persistent data structures in main memory, whereas under DOS 
or Unix the output from one program almost always has to be written to 
disk before it can be loaded into a second program.

Oberon loads modules dynamically on demand, like Windows DLLs, and 
they then remain memory resident unless the user manually issues a 
<module>.Free command. Machines, like the Ceres workstation, which 
possess a hardware MMU (Memory Management Unit) use it to load modules 
by raising page faults, and to protect modules once in memory. The 
Oberon kernel contains a garbage collector which operates in the 
background (ie. between procedure calls) to free up heap space that is 
no longer in use, so freeing Oberon programmers from the chore of 
explicit memory deallocation and all the infuriatingly obscure bugs it 
can introduce.

The Oberon compiler has no separate linking phase, since all linking 
takes place at module load-time (again like a DLL). This saves on 
system resources in two significant ways. Firstly, the binary images 
of 'programs' on disk are minimally small as they don't contain linked 
copies of all the modules they import -- contrast DOS, where you might 
have several applications on your hard disk that each contain a linked 
copy of the same huge graphics library. Secondly less RAM is consumed 
because only one copy of any module is ever loaded, no matter how many 
client modules share it. As a third bonus, whenever you upgrade to a 
new module version, all its clients automatically get upgraded too.

Oberon is a single process operating system, but you can run multiple 
tasks through a very simple form of task switching. When you select a 
new viewer as the target for future commands you are in effect 
switching tasks, but only one command can be executing at any time. 
Whenever it is not executing a command, Oberon runs a single central 
polling loop that watches for keyboard, mouse and network events (see 
fig. 2). To prevent such events being lost while the CPU is executing 
a command, they are queued in buffers controlled via hardware 
interrupts; these interrupts are hidden within their respective device 
drivers and simply return control to the point of interruption, so 
they are invisible to user programs. A programmer can insert new code 
into the polling loop, but only to monitor new event sources such as a 
modem port.

As long as commands are quick in execution (normally the case since 
they are non-interactive) this simple scheme produces an effective 
illusion of multitasking, rather like TSR programs under DOS, but of 
course if you write a command that computes a billion decimal places 
of pi it will tie up the machine. On the plus side, the operating 
system is very robust since tasks can never interact in unexpected 
ways, which eliminates huge swathes of protection code that would 
otherwise be needed. The Oberon disk file system is equally simple, 
and uses a B-tree directory structure for speedy access.

The most important single design feature of Oberon is the decoupling 
of data from the way it is viewed. Viewers display the contents of 
abstract documents such as texts, graphs and pictures. Documents are 
active objects which contain commands to change their own contents, 
and whenever such a change occurs, the document broadcasts a message 
to all viewers so they can update their views of it. In short, 
documents are responsible for their own content, while viewers know 
how to format and display that content -- the generic viewer object 
(called a 'frame') does not need to know the type of its contents. 
This decoupling enables you to extend the Oberon system by adding new 
document types and their viewers without recompiling or duplicating 
ANY of the code of their parent types. It also means that adding new 
commands to an existing document type cannot interfere in any way with 
the operations of its viewer.

Fig. 3 shows a graph of module dependencies for the Oberon core, where 
arrows signify one module importing another (where an indirect path 
also exists, direct imports have been omitted for clarity). It's a 
strictly hierarchical, acyclic, structure with hardware-dependency 
entirely confined to the driver layer. In Wirth's description the 
system 'imports hardware' at the bottom level and 'exports commands to 
the user' at the top level. The whole core operating system occupies 
only 131 Kbytes INCLUDING the Oberon compiler, which is smaller than 
most Windows utilities. There are only three assembler modules 
(Kernel, Display and Reals) all the rest being written in Oberon, and 
the 12,000 lines of source code for these is supplied with the system. 
It's quite feasible (Wirth would probably say desirable) for a 
programmer to understand the workings of the whole operating system.


TEXTS AND WRITE ELEMENTS

The abstract data type Text has a special importance in Oberon, and is 
encapsulated at the heart of the operating system. An Oberon text is 
defined as a sequence of attributed characters, whose attributes are 
ASCII code, font, color and vertical offset (the last three are 
collectively called a 'look'). Text is a far more powerful concept 
than String, the building block of more conventional systems, since it 
already includes the concept of appearance. Texts are divided up into 
'runs', sequences of characters that all share the same look.

Texts are active objects which know how to edit themselves, through 
the basic methods Delete, Insert, Append and ChangeLooks, and how to 
Store and Load themselves from disk. They do not know about font 
rendering or printing, which is the job of their viewer, an object of 
type TextFrame. A TextFrame clips a text to fit the viewing window and 
renders the characters onto the screen using Oberon's built-in font 
engine. Since all interaction with the user occurs via viewers, a 
TextFrame also tracks the mouse and interprets editing commands (via 
its handler procedure) which are passed to the text itself for 
execution. TextFrames employ a very efficient single pass font 
rendering algorithm which expects a fixed line spacing throughout the 
frame, so you can't mix different font sizes in the same frame, though 
you can mix different styles. However frames are nestable, so Oberon 
text editors employ embedded subframes to display headlines etc.

Write is one such text editor, written by Clemens A. Szyperski and now 
shipped as part of the Oberon system. Write extends the concept of a 
text to a sequence of attributed 'elements', where an element can be a 
ordinary character or an extended active (or even interactive) object. 
Write elements float in the text sequence like any other character, 
but the screen display they produce may be radically different; maybe 
a box containing a picture; a 'hot' graph display; or even a whole 
interactive application like a CAD drawing editor. Elements are not 
IMPLEMENTED as frames, which would violate the decoupling of data from 
view, but they are free to INSTALL a subframe with a new set of 
commands tailored to their own purpose. When a viewer encounters an 
element it sends it the 'prepare' message, and the element replies to 
tell the viewer how much screen space it will require. Write elements 
allow you to edit any kind of data object in situ, using its own 
appropriate editor, merely by clicking the mouse within its frame; the 
same effect as Microsoft's OLE achieved elegantly and implicitly 
rather than as a bolted-on afterthought.

From a portability viewpoint Write elements possess one very 
attractive feature -- you can still process a document containing 
elements even if their required code module is not available. Such 
elements just appear as character-sized empty boxes embedded in the 
text. As soon as you acquire the necessary module, the elements 'come 
to life' again.

Write formats documents by embedding markers in the text which affect 
all text up to the next marker. These markers are called 'parcs', 
short for PARagraph Control elements. Parcs normally appear as white 
space but the Write.Parcs command makes them visible as 
Macintosh-style ruler lines, and you can apply various mouse click 
combinations to a visible parc to alter the layout and look of the 
following paragraph interactively. 

ETH students have written dozens of special Write element types. For 
example ErrorElems are placed by the Oberon compiler next to errors in 
your program text; they display an error message when you click on 
them and disappear upon re-compilation. Adaptive LineElems draw 
horizontal rules that automatically adjust to the margin width. 
TableElems display structured tables, and clicking on them displays 
the declarative description of the table format for editing. 
StyleElems are named parcs that define global styles. CalcElems are 
spreadsheet cells. FoldElems collapse a text like an outliner. 
PopupElems produce a pop-up menu, allowing you create new user 
interfaces. Other elements let you embed buttons, icons and hypertext 
links. Any programmer can write new element types to turn Write into a 
customized editor.

I first used the Oberon system on a very special custom workstation 
called Chameleon, developed by Cuno Pfister and Beat Heeb at ETH. This 
remarkable machine contains a fast MIPS3000 RISC processor, seven 
Algotronix CAL1024 field programmable gate-array chips and very little 
else apart from memory and a color palette. One of the CAL chips is 
programmed at boot-time to implement the workstation's I/O and display 
logic, and the remaining six are free for the engineer-user to develop 
custom circuits. The whole Chameleon machine is specified in a 
hardware design language called Debora which strongly resembles 
Oberon, and was completed in three months from scratch! Pfister and 
Heeb have extended Write with interactive custom elements to create a 
visual CAL layout editor, a circuit simulator called DebSim, and a 
graphical CAL debugger that displays the state of CAL elements in 
real-time. The documentation contains active illustrations which are 
not just pictures but spring to life when you click them.

A CLEAN START

When I first wrote about the Oberon language two years ago I 
restrained myself from describing the operating system because it 
seemed too remote from mainstream commercial computing. How quickly 
things change. Now both the IBM/Apple/Taligent consortium and 
Microsoft boast of their adoption of 'microkernels' for future 
versions of their operating systems, as well as extensibility through 
deep object-orientation. Everyone has finally realized that you can't 
plaster new layers over already bloated systems for ever, that a 
return to clean roots is necessary. The big OS vendors won't go so far 
down the road of minimalism as Wirth and Gutknecht have, because 
they've spent years convincing users that they need preemptive 
multitasking and overlapping windows. Nevertheless the Oberon system 
is a beautiful example of how to do more with less, which you can 
sample for free as a peek into an alternative future.

INFORMATION PANEL

Oberon implementations for Apple Macintosh II, Digital Equipment
DECstation, IBM PC (MS-DOS), IBM R/S6000 and Sun SPARCstation are
available without fee (there may be a shipping charge) from :-

The Secretary,
Institut fur Computersysteme,
ETH,
8092 Zurich,
Switzerland.
Tel: (+41-1)-254-7311
Fax: (+41-1)-261-5389

The Oberon System is described in full in :-

Project Oberon -- Niklaus Wirth and Jurg Gutknecht
ISBN 0-201-54428-8
The Oberon System User Guide and Programmer's Manual -- Martin Reiser
ISBN 0-201-54422-9
Programming in Oberon -- Martin Reiser and Niklaus Wirth
ISBN 0-201-56543-9
All published by Addison-Wesley


[Mike -- Fig.1 will be a screen-shot of an Oberon display which I'll 
send on later when my PC version arrives].

Comments