Archive-name: beta-language-faq
Last-modified: Mar 30, 1999
Version: 1.15 (last public version 1.12 - dated: May 07, 1998)
Maintained-by: Jørgen Lindskov Knudsen <>

BETA: Frequently Asked Questions (FAQ)

This question-and-answer list is posted regularly to the BETA mail group, and to the Usenet newsgroups comp.lang.beta, comp.answers, and news.answers.

Please send corrections, additions and comments to Jørgen Lindskov Knudsen (

This information is abstracted and condensed from the posts of many different contributors. No guarantees are made regarding its accuracy.

There are several ways to get this document: More information on BETA can be found on:

Changes since version 1.12

New entries:

Changed entries:

In addition, a number of minor changes and corrections have been made to other entries.


PART I: Frequently Asked Questions

Q01) What is BETA?

BETA is a modern object-oriented language with comprehensive facilities for procedural and functional programming. BETA has powerful abstraction mechanisms than provide excellent support for design and implementation, including data definition for persistent data. The abstraction mechanisms include support for identification of objects, classification, and composition. BETA is a strongly typed language (like Simula, Eiffel, and C++), with most type checking being carried out at compile-time.

The abstraction mechanisms include class, procedure, function, coroutine, process, exception, and many more, all unified into the ultimate abstraction mechanism: the pattern. In addition to the pattern, BETA has subpattern, virtual pattern, and pattern variable.

BETA does not only allow for passive objects as in Smalltalk, C++, and Eiffel. BETA objects may also act as coroutines, making it possible to model alternating sequential processes and quasi-parallel processes. BETA coroutines may also be executed concurrently with supported facilities for synchronization and communication, including monitors and rendezvous communication.

Q02) Where did BETA come from?

BETA originates from the Scandinavian school of object-orientation where the first object-oriented language Simula was developed. Object-oriented programming originated with the Simula languages developed at the Norwegian Computing Center, Oslo, in the 1960s. The first Simula language, Simula I, was intended for writing simulation programs. Simula I was later used as a basis for defining a general-purpose programming language, Simula 67 (later renamed to Simula). Simula has been used by a relatively small community for a number of years, although it has had a major impact on research in computer science.

The BETA language development process started out in 1975 with the aim to develop concepts, constructs and tools for programming, partly based on the Simula languages. The BETA language team consists of Bent Bruun Kristensen, Birger Møller-Pedersen, Ole Lehrmann Madsen, and Kristen Nygaard. Kristen Nygaard was one of the two original designers of the Simula languages.

Q03) What BETA products and services are available?

Currently there is only one supplier of BETA products, namely Mjølner Informatics, who is marketing an entire development system (the Mjølner System) based on the BETA language.

Mjølner Informatics offers the Mjølner System technology to other commercial organizations who are interested in building BETA products (such as alternative development systems), or who are interested in developing value-added products for the Mjølner System. This offer is based on licensing of the implementation of the existing system (including source code, if needed).

Mjølner Informatics
Helsingforsgade 27
DK-8200 Aarhus N
Phone: +45 70 27 43 43
Fax: +45 70 27 43 44

Q04) Are there any school or student discounts?

Generally, the Mjolner System is freely available directly from Mjølner Informatics. Visit the download area for more information.

Thus discounts are not an issue.

Q05) Is BETA available in the public domain?

The BETA language definition is in the public domain. A reference manual on the language is in progress (release-date not fixed yet).

The Mjolner System is freely available from Mjølner Informatics. Visit the download area for more information.

Kai Petzke has initiated a project for writing a freeware compiler for BETA. It is implemented as a translator of BETA to C. For more information and to download a working copy of the compiler, that understands most of BETA's grammatical terms, see the web page:

Q06) What books are available for learning about BETA?

The ultimate source of information on the BETA language is:
Ole Lehrmann Madsen, Birger Møller-Pedersen, Kristen Nygaard:
"Object-Oriented Programming in the BETA Programming Language"
Addison-Wesley and ACM Press, 1993
ISBN 0-201-62430-3
An german introduction to BETA can be found in the book:
Ernst Erich Doberkat, Stefan Dißmann:
"Einführung in die objectkorientierte Programmierung mit BETA"
Addison-Wesley-Longman, 1996
ISBN 3-8273-1026-1
The Mjølner System and the BETA language is also extensively described in the book:
Jørgen Lindskov Knudsen, Mats Löfgren, Ole Lehrmann Madsen, Boris Magnusson (eds.):
"Object-Oriented Environments: The Mjølner Approach"
Prentice-Hall, 1993
ISBN 0-13-009291-6

Q07) Does an introduction to BETA besides the BETA book exist?

The previously mentioned book: "Object-Oriented Environments: The Mjølner Approach" contains an introductory chapter on the BETA language.

Besides, various current activities indicate that introductory material in the form of tutorials are in the pipeline.

See also question Q08.

Q08) Are any magazines or newsletters concerning BETA available?

The BETA language has been presented in several conference papers, including the OOPSLA, ECOOP, and TOOLS conferences. BETA has also been described in a couple of articles in Dr. Dobb's Journal, #206, October 1993. Furthermore, Communications of the ACM, Vol. 37, No. 2, February 1994, is a special issue on Hypermedia, including three papers on the use of the Mjølner System (and the BETA language) for building hypermedia systems.

Q09) Are there any user groups related to BETA?

Yes, there is a user group hosted by Mjølner Informatics. The user group is primarily organized around the BETA mailing list:

The BETA user group is one of the important sources of information on the developments of the Mjølner System, and an important source of information to Mjølner Informatics on the users' expectations for future developments.

See also question Q10.

Q10) Are there any mailing lists related to BETA?

There is a mailing list for BETA, organized by Mjølner Informatics: In order to be added to the mailing list, please send a empty mail to: To be removed, send an empty mail to: Mail sent to the mailing list is automatically forwarded to the comp.lang.beta newsgroup and news posted on the newsgroup is automatically forwarded to the mailing list. The mailing list is lightly moderated to avoid spam.

Q11) Are there any newsgroups related to BETA?

The comp.lang.beta Usenet newsgroup is available for discussing issues related to the BETA language.

Postings to comp.lang.beta are automatically forwarded (moderated) to the mailing list and mails to the mailing list is automatically posted to the newsgroup.

Q12) Is there an archive of BETA postings?

Mjølner Informatics keeps an archive of the BETA mailing list. Send an empty email to for information on accessing this archive.

In addition, the University of Aarhus maintains an archive of all postings to the comp.lang.beta newsgroup, available at:

The former is updated daily, the latter annually.

Q13) Are there any conferences for BETA users?

There are no conferences devoted entirely to the BETA language and development system. BETA shares the spotlight with other object-oriented languages including C++, Eiffel, and Smalltalk in conferences like:

the major international conference devoted to the applications of Object-Oriented technology.
the European Conference on Object-Oriented Programming.
the major international conference on Object-Oriented Programming, Systems, Languages, and Applications.

Q14) Is BETA available on PC, Mac, NeXT, Amiga, Atari, ...?

Currently, BETA is available on UNIX workstations, on PowerPC Macintosh and on Intel-based PCs.

On UNIX, the platforms supported are: Sun Sparc (Solaris), HP 9000 (series 700) and Silicon Graphics MIPS machines running IRIX 5.3 or 6.

Mjølner System is also available for Linux (386/486/Pentium). Linux is a very popular freely available UNIX implementation (for more information, see

Mjølner System is also available for Windows 95, 98, 2000 and Windows NT (386/486/Pentium and compatibles).

There are no current plans to port the Mjølner System to neither DOS nor Windows 3.1 due to the 16-bit addressing and 8-character filename limitations.

Although not officially confirmed by Mjølner Informatics, users of the Mjølner System have reported that the Mjølner System can be effectively used on Amiga 4000 machines under the MacOS simulator, with an execution speed reported to be comparable to that of an HP 9000/425 workstation.

The following additional info is kindly supplied by Juha Makinen <Juha.Makinen@cs.Helsinki.FI>:

Actually this program is an emulator, because it can run native Apple Macintosh 680x0-code in Amigas. The name of this program is an Emplant and it is a 99,9% compatible Apple Macintosh emulator. It emulates the Machintosh (like Quadra) even faster than an equivalent Macintosh is running with the same processor and clock-speed. (This is due to separate graphics, I/O etc. co-processors found on motherboard of the Amiga. Some programs show two times better performance.)

The program is an multi-platform -emulator and can also multitask another emulation and/or AmigaOS on the backgroud. There is a rival (Amax IV) for this emulation-program, but it is only 99,5% Macintosh-compatible and is not supported as widely as this one is. (I'm not sure which one the original author refers to, but I'm quite sure that you can run Beta-compiler on Emplant with Macintosh Emulation. Every program which run in original Quadra should run on Emplant.)

And as an addition, you can run Emplant-emulator also on the Amiga 3000 (and A2000 if you have a processor-card with MMU).

Q15) Are there standards for the BETA language?

The definition of the BETA language is in the public domain. This definition is controlled by the original designers of the BETA language: Bent Bruun Kristensen, Ole Lehrmann Madsen, Birger Møller-Pedersen, and Kristen Nygaard. This means that anyone or any company may create a compiler, interpreter, or whatever having to do with BETA.

Currently, no language definition document exist. Work is in progress to write this language definition document. The definition will be given in strict natural language.

See section Q06 and L02 for information on available language descriptions and latest changes to the language.

The BETA and the Mjølner System trademarks are owned and controlled by Mjølner Informatics.

Q16) What is Mjølner, Sif, Valhalla, Bifrost, Yggdrasil, etc.?

Many have wondered about the origins of the strange product names used for parts of the Mjølner System. Due to the origin of the Mjølner BETA System, many of the components of the system bear Nordic names. These Nordic names originate from the Nordic Mythology, and are thus names within the common cultural background of people in the entire Nordic region:

is the name of the hammer of the god Thor. According to the Mythology, this hammer is the perfect tool that cannot fail, that grows with the task, and always returns to the hand of Thor if he throws it at something. Finally about the pronunciation of Mjølner. For English speaking people, the "spelling of the pronunciation" could be: "Myolner" or "Myulner", and for French speaking people it could be: "Mieulnor".
is the name of the Tree of the World, the ash tree of which the crown covers the whole world. The tree gets it power from the gods, from the evil giants, and from the kingdom of the dead. Everything in the world happens under the mighty crown of Yggdrasil. Yggdrasil is the name of the metaprogramming system.
is the name of the luminous bridge, the rainbow, that leads from Midgaard to Asgaard. Midgaard is the place where the human beings live, and Asgaard is the habitat of the Gods in the middle of the world. Bifrost is the name of the graphics system.
is the name of Odin's hall to where all dead warriors come when they have fallen as heroes on the battlefield. Valhalla is the name of the source-level debugger.
is the name of the wife of Thor. Sif is famous for her golden hair. Sif is the name of the hyper structure editor.
is the name of the goddess of love. She lives in Folkvang and is the most beautiful of all women in Asgaard. She owns the golden piece of jewelry Brisingemen. Freja is the name of the CASE tool.
is the name of the wife of Odin and queen of Asgaard. Frigg is the name of the user interface editor.
is the name of the highest ranking god in Asgaard.
is the name of the strongest of all gods. He is the god for all peasants. He is the son of Odin and Frigg and lives together with his wife Sif in Trudvang on the farm Bilskirner which is the biggest house in the world, with 540 floors.

Q17) Is it possible to obtain an evaluation version of the Mjølner System?

The latest release 5.0 of The Mj°lner System can be downloaded free of charge from

Q18) What is the origin of the name BETA?

[Ole Lehrmann Madsen ( writes:]

Originally Beta was just one of a series of languages developed at Nordic universities.

The first object-oriented language Simula was originally designed as a simulation language but it was soon realised that the main ideas could be used for programming in general and this lead to Simula 67, which has class, subclass, virtual function coroutines, etc. It also supplied the first object-oriented framework in the form of Class Simulation which is a set of classes to support the original goal of Simula to write simulation programs.

It turned out that many users of Simula seemed to get more understanding of their problem domain by having to develop a model using Simula than of the actual simulation results.

Kristen Nygaard and others then decided to develop a successor for Simula, but with main focus of system description - not execution. This lead to a language called

In Delta you could express true concurrent objects and use predicates to express state changes. Delta could, however, not be executed. Delta means 'participate' in Norwegian'. [E. Holbaek-Hannsen, P Haandlykken, K. Nygaard: System Description and the Delta Language. Norwegian Computing Center, Publ. no 523, 1973]

When Kristen Nygaard was a visiting professor at Aarhus University in 1973-75, a project was started to develop a programming language based on the Delta ideas. This language should be a (programming language) successor to Simula and was called

In the seventies, it was often assumed that a general programming language was not usable as a systems programming langauge. It was therefore decided to define a systems programming langauge which should also be used to implement Gamma. This language was called
Finally the machine level languages were referred to as
Long story:-)

So what happened to Delta and Gamma?

There is a (big) report describing Delta and there has later been some related work on Delta including using it in a few projects, but it is no longer being used or developed. The language

was a simplified version of Delta and the result of attempts to formalize Delta by means of Petri Nets.

The Gamma language was never developed. During the work on Beta it was soon realized that there was no need for Gamma. It turned out that by having powerful abstraction mechanisms in Beta, the Gamma-level could be handled by supplying class libraries and frameworks. You may thus think on the Gamma-level as the libraries and frameworks of the Mjølner System.

And this is where we are today.

Some of the stuff in Delta could be handled by adding constraints to BETA and supporting invariants and pre/post conditions. (The idea of invariants and pre/post conditions for classes were originally suggested by Tony Hoare for Simula. [C.A.R. Hoare: Proof of correctness of data representation, Acta Informatics, 4, 271-281, 1972]

The Mjølner System has some libraries supporting initial versions of constraints and invariants.

It has often discussed changing the name BETA - to avoid the beta-testing jokes. The suggestion for a name change is Scala - Scandinavian Language and also Scala means 'going up'... But so far it has been decided to stick with Beta.

Q19) How to format BETA programs in LaTeX?

The best way to format BETA programs in the LaTeX formatting system is by using the lgrind LaTeX package.

You can use the following lgrind style:

beta|the BETA programming language:\
        :kw=if then else for repeat\
            do inner none this enter exit leave restart suspend\
            and or xor mod div\
This lgrind style can be made available in two different ways:

Q19.1) How to use the BETA lgrind style

When the lgrind style is made available (as above), you can use it in the following way.

Let us assume, that you have a BETA source file called

You are now ready to include the BETA source into a LaTeX document. You do this by inserting the following in the start of the LaTeX document:
Please note, that you only need to insert this once.

This implies, that the lgrind LaTeX style is available. At the position in the document, where you wish the BETA source code, you just insert one of the following:

You insert one lgridfile or lagrind command for each piece of BETA source code, you wish to include in the document.

PART II: Language Issues

L01) What features do BETA have?

BETA replaces classes, procedures, functions, and types by a single abstraction mechanism, called the pattern. It generalizes virtual procedures to virtual patterns, streamlines linguistic notions such as nesting and block structure, and provides a unified framework for sequential, coroutine, and concurrent execution. The resulting language is smaller than Simula in spite of being considerably more expressive.

The pattern concept is the basic construct. A pattern is a description from which objects may be created. Patterns describe all aspects of objects, such as attributes and operations, as seen in traditional object-oriented languages, but also aspects such as parameters and actions, as seen in procedures.

Objects are created from the patterns. Objects may be traditional objects as found in other languages, but they may also be objects which correspond to procedure or function activations, exception occurrences, or even coroutines or concurrent processes.

Objects may be created statically or dynamically and the objects are automatically garbage collected by the runtime system when no references exist to them any longer.

Patterns may be used as superpatterns to other patterns (the subpatterns). This corresponds to traditional class hierarchies, but since patterns may describe other types of objects, inheritance is a structuring means available also for procedures, functions, exceptions, coroutines, and processes.

Patterns may be virtual. This corresponds to traditional virtual procedures but again the generality of the pattern construct implies that also classes, exceptions, coroutines, and processes may be virtual.

Virtual patterns in the form of classes are similar to generic templates in other languages. The prime difference is that the generic parameters (that is, the virtual class patterns) may be further restricted without actually instantiating the generic template. The generality of the pattern also implies that genericity is available for classes, procedures, functions, exceptions, coroutines, and processes.

Patterns may be be handled as first-order values in BETA. This implies the possibility of defining pattern variables which can be assigned pattern references dynamically at runtime. This gives the possibilities for a very dynamic handling of patterns at runtime.

You can find more introductions to the BETA language by looking at

L02) What changes have been made to the BETA language definition?

The BETA language definition has been stable since 1992, apart form the following minor changes:

L02.1) String Literals as References

The pattern text enters and exits a char repetition. This means, that a text may be initialized using constant strings as follows:
      t: @text; 
   do 'hello' -> t; 
Many operations involving texts, however, takes references to texts as enter/exit parameters. This is mainly for efficiency reasons.

To allow easy invocation of such operations on string literals, the following is also allowed:

      t: ^text; 
   do 'hello' -> t[]; 
The semantics of this is, that a text object is instantiated, initialized by the constant string, and finally assigned to the text reference.

L02.2) Simple If

Often the following If statement is used:
      b: @boolean; 
   do (if b//TRUE then ... else ... if); 
The current version of the compiler supports an extension to the BETA language called Simple If. This extension means, that the case-selector // may be omitted, if the evaluation on the left hand side exits a boolean. That is, the above may be written
      b: @boolean; 
   do (if b then ... else ... if); 
Like in the general if-statement, the else part if optional.

L02.3) Xor Primitive

An xor primitive is supported as a basic operation on booleans. That is
      b1, b2, b3: @boolean 
   do b1 xor b2 -> b3 
is possible.

L02.4) Short-circuit Boolean Expressions

Boolean expressions are implemented as short-circuit. That is, in
      B1 or B2 
B2 is not evaluated if B1 is true, and
      B1 and B2
B2 is not evaluated if B1 is false.

L02.4) Labelled imperatives

Labelled imperatives were previously defined in the language in two forms:
   L: Imp;
   (L: Imp1; ...; :L)
The second form has now been removed from the language. Instead, the compiler offers the form
   L: (# do Imp1; ... #)
Note that this form is implemented very efficiently in the case where there are no declarations in the object descriptor (i.e. between (# and do).

L03) How do I deal with concurrency in BETA?

The processes of BETA (concurrent objects) are based on a simple fork-mechanism and semaphores. Based on these mechanisms, pattern definitions are available for shared variables in the form of monitors, and for synchronous process communication based on a port communication metaphor. The abstractions also contain facilities for utilizing future values in connection with process interactions.

L04) How do I deal with persistence in BETA?

The Mjølner System contains a library that implements a persistent store for BETA objects. Any BETA object can be stored into the persistent store and subsequent obtained from the store in a type-safe way. There are no requirements that the persistent objects must inherit from any specific superpattern, and persistent objects are fully type-checked both when saved in the persistent store, and when retrieved from the persistent store.

L05) How do I deal with distribution in BETA?

The Mjølner System contains a distributed object system in which BETA objects may reside on different hosts, and communicate transparently with each others, just as if they were residing on the same host. The objects may even be residing on different host types (e.g. on Macintosh and Unix workstations, respectively).

L06) How do I deal with exception handling in BETA?

Exception handling is dealt with through a predefined library containing basic exception handling facilities. The exception handling facilities are fully implemented within the standard BETA language in the form of a library pattern, and the usage is often in the form of virtual patterns, inheriting from this library pattern.

L07) Can classes be treated as first-order elements in BETA?

Yes, they can. This is possible by using the pattern variable construct in BETA. A pattern variable may dynamically be assigned pattern references. Pattern variables may be used to dynamically create instances of the pattern, currently contained in the pattern variable.

L08) What about garbage collection in BETA?

Garbage collection is conducted automatically by the BETA runtime system when it is discovered that no references to the object exist. The garbage collection mechanism is based on generation-based scavenging. The implemented garbage collection system is very efficient.

L09) How do I create a "parameterized class"?

A parameterized class (a template in C++ or a generic class in Eiffel) is created in BETA by using the virtual pattern mechanism. The generic parameter is specified as a virtual attribute of the pattern, and subpatterns of this patterns may now make further restrictions on the generic parameter by further binding the virtual attribute. Generic instantiation is done by either making a final binding of the virtual attribute, or by instantiating an object directly from the pattern.

L10) What is the difference between a virtual binding, a further binding and a final binding (i.e. between :<, ::<, and ::)?

To illustrate the difference between new and further-bindings, consider
   p:  (# v:<  (# do ...; inner #) #);
   q: p(# v::< (# do ...        #) #);
   r: p(# v:<  (# do ...        #) #);
in which a pattern p with a virtual attribute v, and two subpatterns, q and r, are declared. Pattern q further-binds p's virtual attribute, while pattern r declares a new virtual attribute v which has no connection to p's v, except that it happens to have the same name. [This may or may not be what the programmer intended, so perhaps a warning should be issued in this case.]

Thus, if rp is a pointer of type p, and rp happens to denote a q object, then calling rp.v will cause q's v part to be executed in addition to p's (because v has been further-bound in q). However, if rp denotes an r object, then calling rp.v will cause only p's v part to be executed, not r's (because p's v attribute has not been further-bound). [Of course, if rr denotes a pointer of type r, then rr.v will cause r's v part to be executed.]

A final binding has the same effect as a further-binding, except that it specifies that the virtual may not be further-bound from this point on. There are (at least) three different reasons why you might want to use final bindings:

L11) What about invariants in BETA?

Invariants are not an integrated part of the BETA language. However, it is possible to create an invariant system as a framework or library, entirely written in BETA. In the Mjølner System, an experimental invariant system is available. The system offers class invariants as well as pre- and post-conditions for operations. The invariant system also offers the ability to control whether the invariants are checked or not, either on individual object basis or system-wide.

L12) What about change propagation in BETA?

Change propagation (as in Model-View-Control - MVC) is also available in BETA (with extended facilities). Change propagation is available as an experimental part of the current system.

L13) What about futures in BETA?

Futures are used in concurrent programming to return results from a concurrent computation, even before they have been calculated. The result can then be passed around as any other value, and only when an attempt is made to access it, the reader will be blocked until the result is made available by the concurrent computation. Based on the existing BETA facilities, futures can easily be implemented, and an experimental futures library is available as part of the current system.

L14) Why can variables declared in execution blocks not be accessed in INNER?

Consider the following code fragment:
   P: (# do ...; (# x: ... do inner P #); ... #)
   PP: P(# do ... #)
According to the BETA visibility rules, x may not be referenced from the do-part of PP. Why?

The answer lies in the fact that patterns may have more than one inner section. Consider the following (slightly modified) example, where inners are placed in different inserted descriptors, each containing declarations of different sets of local variables:

   P: (#
      do ...;
         (# x: ... do inner P #); 
         (# y: ... do inner P #);
   PP: P(# do ... #)
In this case, the do-part of PP is executed twice via inner, but with different sets of local variables (x and y, respectively). It is therefore meaningless to refer to any one of these in the do-part of PP.

L15) How do I implement a copy (or clone) operation?

It is often useful to be able to make a genuine copy of an object. It is currently being discussed to introduce a 'clone' operation into the object pattern, which should take care of this copying automatically, but no decision has been made as to how and when.

Until then, the following trick does the job:

   P: (# (* internal P structures *)
         copy:< (* generic copy operation *)
           (# copyType: ##P;
              theCopy: ^P;
           do this(P)##->copyType##;
              (* insert here code to  implement the copying
               * of internal P structures into theCopy *)
              INNER copy;
              (* possible finalization of the copying process *)
           exit theCopy[]

   Q: P(# (* internal Q structures *)
            (# Qcopy: ^Q 
            do theCopy[]->Qcopy[];
              (* insert here code to  implement the copying
               * of internal Q structures into Qcopy *)
              INNER copy;
              (* possible finalization of the Q copying process *)
   R: Q(# (* internal R structures *)
            (# Rcopy: ^R 
            do theCopy[]->Rcopy[];
              (* insert here code to  implement the copying
               * of internal R structures into Rcopy *)
              INNER copy;
              (* possible finalization of the R copying process *)
Given the declarations
   a: @R;
   aCopy: ^R;
will make a copy of the a object with the proper qualification (here R), and a state that is a copy of the state of a.

Note: The

      Rcopy: ^R 
   do theCopy[]->Rcopy[]
part of the copy further binding is an inconvenience, but is necessary to persuade the type system to allow remote access to the R-parts of the theCopy object.

L16) Why doesn't BETA have multiple inheritance?

[Ole Lehrmann Madsen ( writes:]

I shall try to explain why there is no (traditional) multiple inheritance in BETA. Please note that I am not trying to argue against MI. The following is only an attempt to explain why it is not in BETA.

When BETA was designed we did not think that the concept of multiple inheritance was ready for being incorporated in the language. One of the main design goals for BETA was that it should be good for modelling. Most usages of MI seemed to be for pure code reuse, i.e. a new class may be defined by inheriting from a number of classes and then redefining the parts that should differ. Often this is done without there being any conceptual relation between the new class and the ones it inherits from. We did not like that way of using inheritance.

MI in BETA should be there to model classification hierarchies which are non-tree structured. In my experience, such hierarchies are rare in practice. What is more common is that you may want several independent tree-structured classification hierarchies for the same objects. A set of person objects might be classified according to their profession, nationality, and religion. This gives three class-hierarchies. People often handle such situation using MI, but this will merge the hierarchies in a way that makes it difficult to identify the three original ones.

We would like to support such independent classification hierarchies in BETA, but no concrete proposal exists.

The various proposals for solving name conflicts and overlapping superclasses also seemed rather complex. We did not want the semantics of basic constructs to be complicated to understand.

For BETA there are a number of additional problems:

Finally, we have not felt an strong need to support MI in the traditional sense, since BETA has other means for handling some of the most common MI cases:

In BETA you may inherit from part-objects and at the same time further-bind its virtuals:

   A: (# f:< ... #);
   B: (# g:< ... #);
   C: (# ...
         X: @A(# f::< (# ... #); ... #);
         Y: @B(# g::< (# ... #); ... #);
X and Y are singular part-objects; due to BETA's block structure the virtual bindings of f and g may refer to variables in the enclosing C-object.

Given the declaration W: ^C, the functions f and g may be invoked as W.X.f and W.Y.g. The difference from MI is that you have to qualify using X and Y. Some people think of this as an inconvenience; others think of it as an advantage since it forces them to be explicit about name conflicts between A and B. If you prefer writing W.f and W.g, you may define f and g functions in C and let them forward the calls to X.f and Y.g.

Given the declaration V: ^A, then W.X[]->V[] is possible, and an invocation of V.f calls the further-binding of f in X, thereby possibly accessing/changing the state of C.

To sum up, this form of multiple inheritance via part objects is very similar to non-overlapping inheritance in C++.

As a final example, consider the following well-known MI case:

                 /      \        
   WindowWithBorder    WindowWithTitle
                 \      /       
In BETA this may be handled using block-structure
     (# ...
        Border: (# ... #);
        Title: (# ... #);
   W1: @Window(# B: @Border; T: @Title #);
   W2: @Window(# T1,T2: @Title #);
Here W1 has a border and a title, whereas W2 has no border and two titles. (For a further discussion, see K. Østerby: "Parts, Wholes, and Subclasses", Proceedings of the 1990 European Simulation Multiconference, pages 259-263, 1990.)

To sum up, we did not think that traditional MI has been worth the complications it will add to the language, since many of the MI cases can be handled by other means. We are, however, still discussing MI, and it may end up being supported more directly.

L17) What is the rationale behind the syntax of BETA?

[Ole Lehrmann Madsen ( writes:]

When we designed BETA, we spent a lot of time discussing syntax - it is one of those things people can really disagree about. We tried to develop what we considered to be a nice and readable syntax with as few long keywords as possible.

The following type of brackets are used:

     (# ... #)     object
     (* ... *)     comment
    (if ... if)    if-imperative
   (for ... for)   for-imperative
We did consider using { and } for objects or comments, but ended up not doing it; we did not feel a strong need to have BETA look like C.

As we did not like long keywords (as in Pascal or Ada), BETA uses symbols like @, ^, |, and :< instead. We believe that for a small language like BETA, it is an advantage to have a compact syntax. This way, you can have more code on a page or in a window. (Of course, {,} is shorter than (#,#), but we preferred the syntax to be consistent with (if,if), etc.)

It is not our experience that the syntax of BETA presents any obstacle to learning the language. BETA has very few constructs (and symbols), and while they may seem strange at first, they are easy to learn and use. Try it!

You can find a quick overview of the BETA syntax by looking at the BETA Quick Reference Card at

L18) How do the scope rules of BETA actually work?

The BETA scope rules may seem slightly complex to the new BETA programmer, but are actually rather intuitive and simple. There are three visibility rules:
  1. Names declared in the descriptor itself are visible within the descriptor.
  2. Names declared in the superpattern of a descriptor are visible within the descriptor.
  3. Names declared in outer blocks (i.e. enclosing descriptors) are visible within the descriptor.
These rules are applied in order to find the definition for a given name application: Note: This method implies that it is possible to reuse the same name for different declarations, as long as the declarations are in different descriptors.

To see how the rules interact, take a look at the example program below. It illustrates most of the combinations, and has the resulting output is shown in comments after each imperative.

   (# a: (# do 1->screen.putint #);
      P1: (# do a; INNER P1 #);
      P2: (# a: (# do 2->screen.putint #);
          do a
      P3: P1(# do a #);
      P4: P1(# a: (# do 3->screen.putint #);
          do a
      P5: P1(# foo1: (# do a; inner foo1 #);
               foo2: (# a: (# do 4->screen.putint #)
                     do a; inner foo2
      P6: P5(# a: (# do 5->screen.putint #);
               foo3: (# do a; inner foo3 #);
               foo4: foo1(# do a; inner foo4 #);
               foo5: foo2(# do a; inner foo5 #);
      P: @P6;
      a;                (*   1 *)
      P1;               (*   1 *)
      P2;               (*   2 *)
      P3;               (*  11 *)
      P4;               (*  13 *)
      P5;               (*   1 *)
      P6;               (*   1 *)
      P.foo1;           (*   1 *)
      P.foo2;           (*   4 *)
      P.foo3;           (*   5 *)
      P.foo4;           (*  15 *)
      P.foo5;           (*  44 *)
      P.foo1(# do a #); (*  11 *)
      P.foo2(# do a #); (*  44 *)
      P.foo3(# do a #); (*  51 *)
      P.foo4(# do a #); (* 151 *)
      P.foo5(# do a #); (* 444 *)

L19) What is a pattern?

The following is an attempt to explain the pattern concept. The description is divided into two parts: a description in the form of examples, and a more abstract explanation.

To begin with, think of a pattern as a generic word for the concepts class, procedure and function. This is not all there is to it, but it will get you started. In BETA, a pattern is anything starting with (# and ending with #). As a simple example, here is a function that multiplies two numbers:

   multiply: (# a,b: @integer;
             enter (a,b)
             exit a*b
The multiply pattern takes two integers, a and b, and returns their product. These kinds of patterns are often called functional patterns, since their use correspond to functions (or procedures) in other languages. In BETA, a call to multiply might look like:
putInt is a procedure that writes the result on the screen.

As another example, let's build a stack class in the typical object-oriented paradigm:

   stack: (# content: [100] @integer;
             currentSize: @integer;
             push: (# e: @integer;
                   enter e
                   do currentSize+1->currentSize;
             empty: (# exit (currentSize=0) #);
             pop: (# e: @integer;
                  do content[currentSize]->e;
                  exit e
Now, stack is also just a pattern. You may call it a class pattern since its meant to be used as a class: to make instances, the actual stacks. And just in case you were wondering: Yes, the push, empty, and pop methods defined for stack are also patterns (functional/procedural patterns), defined inside the stack pattern.

BETA offers a lot of extra functionality which could make the example much more realistic (information hiding, generic stacks, exceptions due to overflow, dynamic expansion of the stack capacity, etc.), but let's keep the example simple.

Having shown a few practical examples, here's the more elaborate explanation:

A pattern is used for instantiating objects (static objects, dynamic objects, inserted objects, etc.). A pattern declaration in its full form looks like this (other forms below):

   P: S(# decl1; decl2; ... decln;
       enter enterlist
       do imperatives
       exit exitlist
This declares P as a (direct) subpattern of S. (S thus is the (direct) superpattern of P.) S may be omitted, in which case object (the direct or indirect superpattern of all patterns) is assumed. Each part (declarations, enter part, do part and exit part) can be omitted. (Thus "P: (# #);" is legal.)

Each declaration can be a declaration of a pattern, a virtual pattern, a further or final binding of a previously declared virtual pattern, a static item, a dynamic item, a static component, a dynamic component, a repetition (array) or a pattern variable (used for holding a pattern, popularly speaking). Or a number of same.

Thus the above declaration of P fits into an outer pattern. If both P and S have declared enter parts, the enter list of a P object consists of the enter lists concatenated. The same goes for the exit list. Thus the subpattern declaration can only add to the enter and exit lists, not make other changes. A bit more complicated rules exist for do-parts, but the basic principle is the same: only additions are possible.

A pattern can be virtual. There are three forms of virtual pattern declarations:

   P: (# V:< Q; #);
   P: (# V:< Q(# ... #); #);
   P: (# V:< (# ... #); #);
where Q is a pattern name.

(For the sake of completeness, this should perhaps be written as

   P: S(# ...; V:< Q; ...; enter ... do ... exit ... #);
   P: S(# ...; V:< R(# ...; enter ... do ... exit ... #); ...;
       enter ... do ... exit ...
etc., but we'll leave the that out.)

Virtual declarations can be extended, or further bound, in subpatterns:

   P1: P(# V::< Q1; #);
   P1: P(# V::< Q1(# ... #); #);
   P1: P(# V::< (# ... #); #);
In the first two forms, it is required that one of the following two conditions holds:
  1. V was declared in P (or some superpattern of P) as V:< Q, and Q1 is a direct or indirect subpattern of Q.
  2. V was already further bound in P (or some superpattern of P) using the form V::< Q0, and Q1 is a direct or indirect subpattern of Q0.
The third form V::< (# ... #) can be used regardless of which form was used for the previous declaration or further binding of V. In this case, the descriptor (# ... #) is used to automatically form a subpattern. (This form of further binding is the only available one if V is declared using V:< (# ... #), or V has been further bound using V::< Q1(# ... #) or V::< (# ... #).)

Thus, the further binding makes V a subpattern of what it was before.

Finally, a virtual pattern may be final bound. A final binding is a further binding, except (syntactically) :: is used instead of ::<, and (semantically) after a final binding, V is no longer virtual, and can therefore not be further bound. The final binding must otherwise follow the same rules as described above for further bindings.

Also, see Question L10.

L20) Are identifiers and keyworks case-sensitive in BETA?

Neither identifiers nor keywords of the BETA language are case-sensitive. That is, the identifier hello is the same as the identifier HELlo, and the keyword INNER is the same as the keywork inner. However, there is one exception from this rule. Identifiers used for declaring Externals are case-sensitive (due to identifiers in the C programming language being case-sensitible). Please refer to the BETA Compiler Manual for details:

L21) What characters are allowed in BETA identifiers?

The identifiers in the BETA language must obey the following literal syntax:
A BETA indentifier has to start with a letter or '_', and may be followed by a sequence of letters, digits, and '_'.

L22) What is the exact semantics of leave P and restart P, when P is the name of a pattern?

Leave and restart are the very basic local control mechanisms in BETA. Leave and restart are specified by:
restart id
leave id
where id is the name of either a label or an enclosing pattern. When id is an enclosing pattern, id is defined to refer to the do-part of id (hence not to the do-part of any superpattern of id).

Consider the pattern:

   P: A(# ... 
       do (* L1 *)
          leave/restart P;
          (* L2 *)
restart P implies that execution continues at (* L1 *):
This means that restart P has the effect of entering the do-part of P as after an inner in A.
leave P implies that execution continues at (* L2 *):
This means that leave P has the effect that execution continues in the do-part of A after the inner that called the main-do-part of P.
   (# A: (#
         do (for 4 repeat '['->put; INNER; ']'->put for)
      P: A (# k: @integer
	   do k+1->k->putInt;
              (if k=2 then '-'->put; leave P if);
              (if k=3 then '*'->put; restart P if);
   do P
will give the following output:

L23) What is the BETA lexem syntax?

The different lexems in the BETA language grammar (names, strings, and numbers) are not precisely defined in any of the available documents. We will therefore here give the definition:
<NameAppl> =	<NameDecl>
<NameDecl> =    (<letter>|"_")+(<digit>|<letter>|"_")*

<String>   =    "'"<char>*"'"
           where <char> can be any char except "'" and newline.
			"'" are allowed in <String>, iff preceeded with "\".
			"\n", "\t", etc. are allowed in <String> to
			represent non-printable chars - see Compiler
			manual (mia91-02) for details.

<Const>   =     (<int>|<based>|<real>) where
        <int>      = <digit>+
        <based>    = <int>("X"|"x")<basedNum>
	<basedNum> = (<digit>|<letter>)+
        <real>     = <int>["."<int>][("E"|"e")[("+"|"-")]<int>]

<letter>  =     "a"|"b"|...|"z"|"A"|"B"|...|"Z"
<digit>   =     "1"|"2"|...|"9"|"0"
The usage of |, +, *, (...), and [...] conform to standard regular expressions syntax.

L24) What is the maximum length of a BETA identifier?

For most practical cases there is no maximum lenghth of a name. The length of an name is currently limited by the representation of an abstract syntax tree (AST). There is currently a limitation to the size of an AST. In the AST representation, a 16-bit integer is used to represent the length of a name. A name can thus in theory consist of more than 65000 characters. However, it is much more likely that a BETA fragment breaks the limit of an AST than an identifier becomes too large.

L25) What is the exact qualification rules for nested patterns?

In Chapter 8 on Block Structure in the BETA book it is (in section 8.2) said that patterns like Pascal.Symbol and Simula.Symbol are different. The corresponding declarations are as follows
        Grammar: (# ...; Symbol: (# ... #); ... #);
        Pascal: @Grammar;
        Simula: @Grammar;
The current implementation does, however, not consider nested patterns like Pascal.Symbol and Simula.Symbol to be different. The reason for this is historical.

Qualification check was implemented in two stages. First the compile-time checks were implemented, and next the run-time checks. The qualification rules for run-time checking were implemented such that nested pattern like Pascal.Symbol and Simula.Symbol are identical.

This is a relaxation of the proper run-time qualification rule (as defined by the BETA language), and a future release of the MBS will properly implement run-time qualification check.

PART III: Environment Issues

E01) What is the Mjølner System?

The Mjølner System is an integrated and interactive general-purpose software development environment that supports industrial strength programming using object-oriented programming in the BETA programming language.
(Note: "Mjølner System" was formerly designated "Mjølner BETA system".)

E02) What does the Mjølner System contain?

The Mjølner System includes an implementation of the BETA language, a series of libraries and application frameworks, a set of development tools, and a metaprogramming system. All components of the Mjølner System are constructed using the BETA language.

Major parts of the Mjølner System (e.g. the editor, parser, pretty-printer, metaprogramming system, fragment system) are grammar-based in the sense that tool generators exist that, given a specific grammar for a language, will define a specific tool that is able to manipulate programs written in that particular language.

E03) What libraries come with the Mjølner System?

Basic libraries
The basic patterns are the object-oriented variants of the standard simple data types, such as char, boolean, integer, and real. These patterns make it possible to treat e.g. integers as ordinary objects. The basic patterns also includes the Object pattern which is the implicit superpattern for all patterns that have no explicit superpattern.
See the Basic Libraries Manual for more details:
The Stream Patterns
A Stream is a generalization of internal and external text objects. An internal text object (Text) is a sequence (repetition) of chars. An external text object (File) corresponds to a traditional text file. Stream, Text, and File are organized in the following hierarchy:
   Stream: (# ... #);
     Text: Stream(# ... #);
     File: Stream(# ... #);
       UnixFile: File(# ... #);
       MacFile: File(# ... #);
As part of the interface to the operating system, the basic libraries include patterns for accessing the directory structures of hierarchical file systems:
   Directory: (# ... #);
     UnixDirectory: Directory(# ... #);
     MacDirectory: Directory(# ... #);
See the Basic Libraries Manual for more details:
The Process Patterns
The Process interface facilitates execution of subprocesses, communication between several independent processes, client/server architectures, and it is even possible to establish communication between Unix, PC and Macintosh processes.
See the Process Libraries Manual for more details:
The External Language Interface Patterns
To enable interfacing with external languages (such as C), the basic libraries define the external, cStruct, and externalRecord patterns.
See the Basic Libraries Manual for more details:
Container libraries
The standard container data structures are organized in the following inheritance hierarchy of patterns:
             |             |             |              |
         collection arrayContainer sequentialContainer list
       ______|_______         ___________|_______________
       |            |         |       |       |         |
    multiset    hashTable   stack   queue   deque  prioQueue
       |            |
      set   extensibleHashTable
     |                      |
classificationSet   classificationSubSet
Container patterns are generic patterns in the sense that the element type of the elements kept in the container can vary between different container instances.
See the Container Libraries Manual for more details:
Persistent store:
Support for saving any kind of object generated by a BETA program execution on secondary storage and restoring them in another BETA program execution. The persistent store is fully type safe. An object-oriented database for BETA objects is currently under development.
See the Persistence Libraries Manual for more details:
Metaprogramming system libraries:
A metaprogram is a program that manipulates other programs. Yggdrasil is a metaprogramming system that supports creation of metaprograms. Yggdrasil is grammar-based: a metaprogramming environment may be generated from the grammar of any language. The metaprograms manipulate programs through a common representation called abstract syntax trees (ASTs). An AST is modelled as an instance of a pattern. There is a pattern corresponding to each syntactic category (non-terminal) of the grammar. The grammar hierarchy is modelled by a corresponding pattern hierarchy, derived automatically from the grammar.
See the Metaprogramming Libraries Manual for more details:
The latest release (r4.2) of Mjolner System allows the use of SGI's OpenGL library for doing 3D graphics from inside of BETA programs. The library functions as a subsystem of the Graphical User Interface (GUIenv) framework.
It supports platform independent 3D graphics. This means that the same openGL/BETA program will work on different machines with only recompilation required.
The system is not a implementation but does calls to the standard library.
Note that this is the first version and errors may occur. (see Part V for limitations and requirements.)

E04) What frameworks come with the Mjølner System?

Concurrency framework
The basic libraries define various patterns for dealing with concurrency, synchronization, and communication. These patterns are: system, semaphore, fork, monitor, port, restrictedPort, objectPort, qualifiedPort, conc, and alt.
Graphical User Interface framework
The Mjølner System contains from release 4.0 a platform independent framework for the construction of graphical user interfaces, called guienv..
X Window System framework
The Mjølner BETA object-oriented interface to the X Toolkit Intrinsics (Xt) is called XtEnv. This pattern contains the basic patterns common for many user-interface toolkits built upon the X Window System, but it does not contain any higher-level user interface elements. It is typically used together with a widget set containing such user interface elements built on top of it. Examples of such widget sets are the Athena Widgets, OPEN LOOK, and Motif. The Mjølner System currently includes object-oriented interfaces to the Athena Widgets (AwEnv) and to Motif (MotifEnv).
Bifrost graphics framework
The interactive object-oriented graphics system Bifrost is based on the Stencil & Paint imaging model. Bifrost models computer graphics images by abstracting the geometric and color properties of graphical objects. The important new concept introduced in Bifrost is that there is one basic drawing primitive, the graphical object. The graphical object unites interaction, graphics modelling, and graphics context. Bifrost includes extensive support for various kinds of interaction: interactive creation, reshaping, translation, scaling, and rotation of graphical objects. The object-oriented approach makes extensibility and tailorability a simple task, and facilitates object-oriented drawing applications. One of the main goals of the development of Bifrost was to make the graphics system independent of underlying graphics and hardware systems.
Distribution framework
A distributed object system is available for enabling transparent access to BETA objects located on different hosts on the network.
OODB framework
A distributed object-oriented database system for BETA objects is currently being developed.

E05) What tools come with the Mjølner System?

BETA Compiler
The BETA compiler is a native code generation compiler.
Fragment System
The fragment system is used for splitting BETA programs into smaller pieces (fragments). The fragment system is responsible for the dependencies between different fragment files, defining a given library or program. Due to the generality of the fragment system, a BETA program can be divided into smaller pieces in many different ways.
Source Browser
The different tools in the Mjølner System uses the same source browser. This source browser gives easy access to the file system, and gives facilities for browsing in the entire set of source files, belonging to a given program (the dependency graph of the program).
Source-level Debugger
A source-level debugger for the BETA language is available on all platform (except Macintosh and HP-PA). It contains facilities for specifying break-points, single stepping, inspection of object states, inspecting the run-time organization, etc. The debugger has a graphical interface.
Hyper Structure Editor
The Mjølner BETA Hyper Structure Editor has the following properties:
Syntax-directed Editing
Syntax-directed editing makes it possible to construct and edit programs or other documents without introducing syntax errors. Syntax-directed editing is especially useful for application-oriented languages intended for end-users, casual users and beginners that may have difficulties in remembering the concrete syntax.
Abstract Presentation and Browsing
The editor is able to present a program at any level of detail. At the top-level of a program the user may get an overview of classes and procedures. It is then possible to browse through modules and procedures to see more and more details.
Adaptive Pretty-Printing
The editor includes an adaptive pretty-printing algorithm which prints the program or document such that it always fits within the size of the window or paper.
Text Editing and Incremental Parsing
The programmer may freely alternate between syntax-directed editing and textual editing. Any program part may be textually edited using keyboard, mouse, and menus in the usual style known from the Macintosh or the X Window System, respectively. Any program part that has been textually edited is immediately parsed.
Fragment Manipulation and Browsing
The editor provides an interface to the fragment system. It is possible to browse through the fragment structure and to create and combine fragments.
Integration of Program and Documentation
The user may add a comment at any place in a program. The user decides whether or not to display a comment. Also the user decides whether to display a comment as part of the program or in another window; in the latter case a comment is indicated by means of (*). Using abstract presentation it is possible to obtain a pretty-print of a program which includes just the classes and procedure headings and corresponding comments. This makes it possible to extract a functional specification from the program.
Hypertext Facilities
The editor includes hypertext facilities. The facility for handling comments is an example of a hyperlink between a program and a text document. Another type of hyperlink is a link from the use of a name to the declaration of the name (this is only implemented for BETA).
Object-oriented CASE Tool
The Mjølner BETA CASE Tool provides No CASE gap:
User Interface Editor
The graphical user interface editor gives a direct manipulation editor for the user interface of an application. The user interface editor is integrated with the structure editor, enabling both graphical, structured and textual editing of the user interface of the program.
Metaprogramming tools
Supplementing the metaprogramming libraries, there is a number of grammar-based tools as part of the metaprogramming system, such as compiler-compiler, parser, pretty-printer, and the hyper structure editor. Being grammar-based, it is possible to customize them all towards specific grammars.

E06) Does a beta-mode for Emacs exist?

Yes, an Emacs mode for editing BETA programs is part of the Mjølner System. This beta-mode is in the public domain and can be obtained by FTP from the directory

The file beta-mode.el contains a large comment that explains how to use this.

PART IV: Specific Issues

SECTION I: The Fragment System

F01) What is the purpose of the fragment system?

The purpose of the fragment system is to enable modularization of BETA programs. The fragment system also supports separate compilation, dependency analysis of modules, information hiding and separation of specification and implementation modules. The fragment system also enables the co-existence of different implementations of the same specification, depending on the target machine type (on the same file system), and automatic selection of the proper variant for the specific machine type.

The fragment system is based on the slot and fragment metaphors. A slot is a specification in the source code which signifies that separately compiled source code may be associated with that place. A fragment is a piece of source code which can be separately compiled, and associated with a slot.

The fragment system takes care of the slots and fragments, and the connections between them. Several different combination rules exist in the fragment system, enabling the specification of different modularization relations.

F02) How do I separate implementation and specification code?

Let us assume that we has the following source code:
   ORIGIN '...'
   --- lib: attributes ---
   f: (# t: @text; i,j: @integer; r: @real
      enter t[]
      do (* ... some code implementing f ... *)
This source code is assumed to reside in a source code file called

If we want to separate the implementation and the specification, we can make the following change to

   ORIGIN '...';
   BODY 'fBody'
   --- lib: attributes ---
   f: (# t: @text; i,j: @integer; r: @real
      enter t[]
      <<SLOT fBody: dopart>>
That is, we have replaced the implementation with a slot specification.

We now create another source file; let's call it

   ORIGIN 'fSource'
   --- fBody: dopart ---
   do  (* ... some code implementing f ... *)
As can be seen, we have now modularized the implementation away from the specification (except for the i, j, and r attributes (see question F05).

F03) How do I work around "*****Only pattern-declarations may appear in a fragment of category 'attributes'"?

In F02, we didn't get rid of the i, j, and r implementation attributes of f. The reason is that it is not possible to do the most obvious, which would have been the following:
   ORIGIN '...';
   BODY 'fBody'
   --- lib: attributes ---
   f: (# t: @text;
         <<SLOT fLib: attributes>>
      enter t[]
      <<SLOT fBody: dopart>>
   ORIGIN 'fSource'
   --- fLib: attributes ---
   i,j: @integer; r: @real
   --- fBody: dopart ---
   do  (* ... some code implementing f ... *)
since it is not allowed to specify reference attributes (static or dynamic) in attribute slots.

Instead we have to use the following trick:
   ORIGIN '...';
   BODY 'fBody'
   --- lib: attributes ---
   f: (# t: @text;
        fPrivate: @<<SLOT fLib: descriptor>>
      enter t[]
      <<SLOT fBody: dopart>>
   ORIGIN 'fSource'
   --- fLib: descriptor ---
   (# i,j: @integer; r: @real #)
   --- fBody: dopart ---
   do  (* ... some code implementing f ... *)
and in (* ... some code implementing f ... *) we have to change all references to i, j, and r to fPrivate.i, fPrivate.j, and fPrivate.r.

F04) Why can't I have instances in attributes-fragments?

Allowing instances in attribute forms makes separate compilation of fragments very difficult due to problems in calculating the size of objects being allocated from the descriptor in which the fragment form is bound (to a slot). E.g.
   ORIGIN '...'
   --- lib: attributes ---
   f: (# t: @text;
         <<SLOT fLib: attributes>>
      enter t[]
      <<SLOT fBody: dopart>>
   ORIGIN '...';
   INCLUDE 'fSource'
   --- program: descriptor ---
   (# foo: @f
   do (* ... usage of foo ... *)
   ORIGIN 'fSource'
   --- fLib: attributes ---
   i,j: @integer; r: @real
   --- fBody: dopart ---
   do  (* ... some code implementing f ... *)
   ORIGIN 'fSource'
   --- fLib: attributes ---
   i,j,k: @integer; r, s: @real
   --- fBody: dopart ---
   do  (* ... some code implementing f ... *)
   ORIGIN 'fUsage';
   BODY 'fImpl1'
   ORIGIN 'fUsage';
   BODY 'fImpl2'
When compiling the fragment separately, it is impossible to pre-calculate the size of the foo object, since foo will contain i,j,r in, whereas foo will contain i,j,k,r,s in

A solution to this problem is being investigated by Mjølner Informatics, but there are no plan for when this will be supported.

F05) Why can't I have virtual declarations/bindings in attributes-fragments?

There are two problems in allowing virtual declarations in attribute fragments.

The first problem is a logical problem. Consider:
   ORIGIN '...'
   --- lib: attributes ---
   A: (# V:< T;
   B: A(# <<Blib: attributes>>
   C: B(# V::< T1;
   ORIGIN 'fSource'
   --- Blib: attributes ---
   V::< T2
The problem is, that when doing the semantic checking of V::< T1 in C, it is impossible to know the further binding in the fragment, since it may be compiled after the compilation of the fragment. Thus it is impossible to ensure, that the further binding in C is in fact legal (to be legal, T1 must be a subpattern of T and all further bindings that might appear in all fragments later bound to the Blib slot.

The second problem is in calculating the size of the virtual dispatch table, if declaration of new virtuals were allowed in fragments bound to the Blib slot.

F06) What are the differences between the INCLUDE facilities of BETA and C?

It is important to note that the fragment system INCLUDE mechanism is radically different from e.g. the C compilers' #include facility. The C #include mechanism is merely a means for textual composition, without any semantical implication. The fragment system's INCLUDE mechanism is a semantical, separate compilation facility, and at the same time it describes parts of the dependency relations between the program parts.

F07) Why doesn't the compiler complain about a missing inner in a body fragment?

The BETA compiler permits the following fragments:
   ORIGIN '~beta/basiclib/v1.6/betaenv';
   BODY 'testBody'
   --- lib: attributes ---
   test: (# do <<SLOT testBody: descriptor>> #)
   --- program: descriptor ---
   (# do test(# do ... #) #)
   ORIGIN 'top'
   --- testBody: descriptor ---
   (# do (* no inner! *) #)
Why does the compiler allow the specialization of test in the program slot even though there is no inner in the definition of test (as can be seen in the testBody fragment)?

The reason is that the testBody fragment may be compiled separately, and later changed without recompiling or rechecking the fragment. That is, even though the testBody might originally have included an inner, there is no way to ensure that later changes do not remove it (without sacrificing the separate compilation ability).

Note: This behavior is consistent with the compiler not performing flow analysis to ensure that all execution paths of a pattern contain an inner. For example,

   foo: (# do (if true then (* nothing! *) else inner if) #)
   bar: foo(# do ... #);
is legal even though bar's do-part is never executed.

F08) Can <<Attributes>> be used instead of <<AttributeDecl>>?

The fragment system has a pragmatic treatment of the syntactic categories <<AttributeDecl>> and <<Attributes>>. In general one may want to leave slots in a delaration list for inserting declarations as in:
   (# a: @integer;
      <<SLOT lib1: attributes>>;
      b: ^ text;
      <<SLOT lib2: attributes>>;
      c: (# ... #)
It is, however, not possible to generate the above form from the BETA grammar, since the nonterminal <attributes> cannot generate itself. It is possible to make a grammar that can do this, but such a grammar is very likely to be ambiguous. The following fragment can, however, be generated from the grammar:
   (# a: @integer;
      <<SLOT lib1: attributeDecl>>;
      b: ^ text;
      <<SLOT lib2: attributeDecl>>;
      c: (# ... #)
This will, however, only allow one fragment-form to be inserted in a each library slot. To handle this, the fragment system allows a fragment form of category <attributes> to be inserted for an <attributeDecl>. This aliasing between <attributeDecl> and <attributes> is handled by the alias mechanism for the BOBS parser used by the meta programming system. See $(BETALIB)/bobs/vx.y/, nontAlias. The alias mechanism also makes it possible to use <descriptor> as a shorthand for <objectDescriptor>. The use of syntac alias's is pragmatic and does not strictly follow the principles of the fragment system, but it is considered a minor but practical mechanism.

SECTION II: The X libraries

X01) Why does my label widget sometimes get the attribute name as label-string, and sometimes not?

The following BETA program creates a window containing "Label"
   ORIGIN '~beta/Xt/awenv'
   --- program: descriptor --- 
   (# Hello: @Label;
   do Hello.init; 
whereas the following program creates a window containing "Hello"
   ORIGIN '~beta/Xt/awenv'
   --- program: descriptor --- 
   (# Hello: @Label(##);
   do Hello.init; 

The connection between the names used for widgets in BETA and the external names used in the external widgets interfaced to from BETA is that the pattern name of the BETA widget is used for the external widget name by default. In the first example, the Hello widget is an instance of the pattern Label, and in the second example the widget is the only possible instance of the singular pattern Label(##), which is named Hello.

The appearance of the windows in this case comes from the fact that the Athena Label widget uses the external name of the widget as default label-string, if it is not specified otherwise. A variant of this problem is the case where you specify a list of widgets using the same pattern:

   hello1, hello2: @Label(##);
In this case the default name will always be the first name in the list, hello1. To avoid this behavior, use the scheme
   hello1: @Label(##);
   hello2: @Label(##);
or specify the name explicitly instead.
See the X Window System Libraries Manual for more details:

X02) Why do I get the error "There must be only one non-shell widget which is son of Toplevel"?

Consider the following program:
   ORIGIN '~beta/Xt/awenv';
   --- program: descriptor ---
   (# faculty: label
        (# init:: (# do 2-> borderwidth #) #);
      University: @box
        (# Physics, Mathematics: @faculty; 
           init:: (# do Physics.init; Mathematics.init #);
   do University.init;
The idea was that a window with two labels named Physics and Mathematics should appear. But executing it gives the error message
Xt Error: There must be only one non-shell widget which is son of Toplevel. The widget causing the conflict is named faculty.
This is because the program uses the init pattern of the widgets without specifying the father and name of the widgets. In the Xt manual [MIA 91-16], it is briefly explained that the father widget will default to "the enclosing widget according to BETA's scope rules" (see the description of Core in "Basic XtEnv patterns").

To be precise, this is what happens: When the init pattern of a widget is invoked, it first checked to see if the father is NONE. This will be the case if no father is specified in the enter part of init. If so, a search is started in the statical environment of the widget pattern. If a specialization of a Core widget is found, this widget is used as the father. This search is continued until a pattern with no enclosing pattern is found. In this case the widget named TopLevel (in xtenv) is used as the father. The widget TopLevel is an instance of the pattern TopLevelShell, which among its characteristics has the constraint that it wants to have exactly one non-shell child.

Now consider the example program: The first thing that happens is that the init attribute of University is invoked. Since no father is specified, a search for one is started from the University pattern. This search finds the pattern AwEnv(# ... #), which is not a Core, and which has no enclosing pattern. Thus University will get the father widget TopLevel.

The final binding of University.init then invokes Physics.init. Physics is an instance of the pattern faculty, which is declared in the same scope as University. Thus the search for a father for Physics is identical to the search for the father of University, and Physics also gets TopLevel as its father. This is when the error occurs. The reason why the name reported in the error message is faculty is explained in Question X01.

Notice that it did not matter that the instantiation of the Physics object is done within University: the default father is searched for starting from the pattern declaration of the object.

In general there are three possible solutions:

  1. Supply the father and name when initializing the faculty widgets:
       do ("Physics", University)->Physics.init;
          ("Mathematics", University)->Mathematics.init;
    In this case, no search for a default father is needed for the faculty widgets.
  2. Make (possibly empty) specializations of faculty inside University:
       Physics: @faculty(##);
       Mathematics: @faculty(##);
    Now the search for a default father of Physics will start at the pattern faculty(##) inside University, so the University pattern will be the first found in this search, and hence the University widget will become the father of the Physics widget. Likewise for Mathematics.
  3. Move the declaration of the faculty pattern inside the University pattern. This will give the same search path as in solution 2. (Conceptually, this might also be the best place to declare faculty in the first place.)
The above example was a simple one. In more complicated cases, the reason for an error of this kind can be trickier to spot. If your program uses the fragment system to move declarations of useful widgets into a library, this kind of error is likely to occur. Remember that if an instance of an unspecialized widget is used, the widget pattern being declared in, say, the XtEnvLib attributes slot of xtenv, then the search for a default father is started at the XtEnv pattern, and therefore no father widget is found. In this case the widget will get TopLevel as father. Solutions 1 or 2 above will be appropriate in these cases.
See the X Window System Libraries Manual for more details:

X03) How do I get a separate window for my widget?

Widgets that create separate windows which can be individually moved, resized, and so on, by the window manager are specializations of the Shell pattern. Normally you would use a TopLevelShell (the pattern used for the TopLevel widget created by default by XtEnv).

To make the following Athena Label appear in a separate window

   goodbye: @Label(# init:: (# do 'Goodbye World'->label #)
you would wrap a TopLevelShell around it:
   byewindow: @TopLevelShell
     (# goodbye: @Label
          (# init:: (# do 'Goodbye World'->label #) #);
        init:: (# do goodbye.init #);
To make the window appear, it should be initialized like any other widget, and then the Shell method popup should be invoked:
Notice that the first widget initialized by a program will by default become a child of the TopLevel widget (see question X02), and will thus be in a separate window.

There are other possible shells to use, such as OverrideShell. The OverrideShell has gotten its name because although it creates a separate top level window, it overrides all requests from the window manager, and will therefore not be resizable, etc.

X04) Why do I get the error "clockWidgetClass: undefined" when linking my AwEnv program using the xt/v1.8 libraries? [corrected in r4.0]

The X libraries in the Mjølner System are based on X11 release 5 (X11R4/R5). Support for X11R6 is not included in release 3.0 of the Mjølner System. But with a few exceptions, X11R6 is backward compatible with X11R5. One of the few exceptions is the reason for the above error: Some very infrequently used widgets have been removed from the Athena widget set in X11R6.

To fix the error you should have your system administrator apply the following patch to the file ~beta/Xt/v1.8/private/external/awInt.c:

   < #include <X11/Xaw/Clock.h>
   < #include <X11/Xaw/Logo.h>
   < #include <X11/Xaw/Mailbox.h>
   < int getClockWidgetClass(){return ( (long) clockWidgetClass);}
   < int getLogoWidgetClass(){return ( (long) logoWidgetClass);}
   < int getMailboxWidgetClass(){return ( (long) mailboxWidgetClass);}
That is, remove all lines referring to the clock, logo, and mailbox widgets. Then the system administrator should compile one of the awenv demos to get the changes incorporated into the system.

X05) Why do I get the error "Error: NULL ArgVal in XtGetValues" when executing my Xt program using the xt/v1.8 libraries? [corrected in r4.0]

This is due to a programming error in the Mjølner System interface to the X toolkit. The error does not seem to influence programs linked under X11 release 5, but (at least) X11R6 on Linux encounters it.

To fix the error have your system administrator change some files:

  1. In the file ~beta/Xt/v1.8/, the definition of the pattern argList should be changed to:
    argList: cStruct
      (# byteSize::< (# do 100->value #);
         max: (# exit R.range div 2 #);
           (# size: @integer;
           enter size
           do (if size=0 then R.range->size
               else size-R.range->size;
         set: @
           (# number: @integer;
              cStr: @integer;
              value: @integer;
           enter (number,cstr,value)
           do (* Cannot check ranges since no GC's may occur.
               * The user needs to do the bookkeeping himself
               * using 'max' and 'extend'.
               * The reason for this is that 'value' may be
               * the computed address of an integer.
         get: @
           (# number: @integer;
           enter number
           exit R[number*2]
         getName: @
           (# number: @integer;
              t: ^text;
           enter number
           do r[2*number-1]->CStringToText->t[];
           exit t[]
  2. In the file ~beta/Xt/v1.8/private/, the two fragments IntegerResourceGet and AncestorSensitiveGet should be changed to:
       --- IntegerResourceGet: dopart ---
       do (1,resourceName, @@value)->private.wargs.set;
       --- AncestorSensitiveGet: dopart ---
       do (1,xtnancestorsensitive,@@value)->private.wargs.set;
  3. In the file ~beta/Xt/v1.8/private/, the fragment FloatResourceGet should be changed to:
       --- FloatResourceGet: descriptor ---
       (# status,res: @integer
       do (1,resourceName,@@value)->private.wargs.set;
  4. In the file ~beta/Xt/v1.8/motif/private/, the three fragments MotifStringResourceGetText, MotifStringResourceGet, and ProcResourceGet should be changed to:
       --- MotifStringResourceGetText: descriptor ---
       (# S: @MotifString; 
       do (1,resourceName,@@S.value)->Private.Wargs.Set;
       --- MotifStringResourceGet: descriptor ---
       do (1,resourceName,@@value)->private.wargs.set;
       --- ProcResourceGet: descriptor ---
       do (1,resourceName,@@p)->private.wargs.set;
  5. In the file ~beta/Xt/v1.8/motif/private/ the two fragments RowColumnLabelStringGetText and RowColumnLabelStringGet should be changed to:
       --- RowColumnLabelStringGetText: descriptor ---
       (# S: @MotifString; 
       do (1,resourceName,@@S.value)->Private.Wargs.Set;
       --- RowColumnLabelStringGet: descriptor ---
       do (1,resourceName,@@value)->private.wargs.set;
  6. Then have your system administrator issue the commands
       cd $BETALIB/Xt/v1.8
       beta -q -c private/ motif/private/
    to get the changed files recompiled.
These changes will be incorporated in version 1.9 of the Xt libraries.

X06) How do I set font information in MotifStrings?

In order to set font information in MotifStrings, you can use the following as a template:
   sensorLabel: @Label
     (# init::
          (# s: @labelString;
             t: @MotifString 
	          (# init::
                       do ('Sensor:','ItalFont',XmSTRING_DIRECTION_L_TO_R)
                            -> t.setTextSegment;
          do (...)                  

X07) Resource specification errors in Xt/v1.9 [corrected in r4.0]

Version 1.9 of the BETA interface to X (part of r4.0) solves most of the errors appearing when using X11R6 (e.g. the errors in X04 and X05).

This is done, among other things, by introducing BooleanResource, CharResource and ShortResource to correctly model the interface to X resources with different physical representations.

Unfortunately a few of the resources was not converted correctly. This means that you may get wrong behaviour when reading these resources.

To fix this you can change the following in the Xt/v1.9 sources, and recompile the libraries (after appropriate setting of permissions):

   Change from IntegerResource to ShortResource:
   motif/         RowColumn.numColumns
   motif/             TextField.columns

   Change from IntegerResource to BooleanResource:
   -----------------------------------------------                   SimpleMenu.menuOnScreen                   Paned.refigureMode                   AsciiText.autoFill                   AsciiText.resize                   AsciiText.displayNonprinting                   CoreLIB.resizable                   Core.mappedWhenManaged                   Shell.allowShellResize                   Shell.overrideRedirect                   Shell.saveUnder                   WMShell.input                   WMShell.transient                   WMShell.waitForWM                   TopLevelShell.iconic
   motif/     BulletinBoard.defaultPosition
   motif/             MotifList.automaticSelection
   motif/             Scale.highlightOnEnter
   motif/             ScrolledText.scrollVertical
   motif/             ScrolledText.scrollHorizontal
   motif/             ScrolledText.scrollLeftSide
   motif/             ScrolledText.scrollTopSide
   motif/             TextField.verifyBell
These errors will naturally be corrected in the next release.

SECTION III: The BETA compiler

C01) What is the execution speed of BETA programs?

For average programs, the execution speed of typical BETA programs is comfortable. However, there are many possibilities for optimization in the current BETA compiler, the generated code, and the run-time system. Mjølner Informatics is constantly working on improving the execution speed of BETA.

C02) How do I get rid of the warning: "A run-time qualification check will be inserted here"?

By using the -q or -w options to the compiler: "beta -q ..." or "beta -w ..."

C03) What *does* that Qua-check warning mean, anyway?

If you have:
   (# Vehicle: (# ... #);
      Bus: Vehicle(# ... #);
      aVehicle: ^Vehicle;
      aBus: ^Bus
   do ...
the compiler will give a Qua-check warning at the "aVehicle[]->aBus[]". The reason is that aBus can only refer to objects which are instances of a pattern that is a subpattern of Bus (or is a Bus). But aVehicle may refer to all objects which are instances of a pattern that is a subpattern of Vehicle (or is a Vehicle) - that is, not necessarily Bus. The BETA runtime system therefore inserts a test to verify that the object referenced by aVehicle[] is actually an instance of a pattern that is a subpattern of Bus (or is a Bus) - otherwise a runtime error occurs.

The Qua-warning is issued to direct your attention towards these places for potential runtime errors.

C04) How do I work around "*****Repetition of non simple patterns is not implemented" (using v5.0 of the compiler)? [corrected in r4.0]

If you want to write:
   persons: [100]@person
(which is not implemented in version 5.0 of the BETA compiler), you should instead write:
   persons: [100]^persons
and then, before you start using the persons repetition, initialize it by:
   (for i: persons.range repeat
Then you can use the persons repetition in the rest of the program, just as if it was declared as a repetition of static persons.

In version 5.1 of the BETA compiler, persons: [100]@person is implemented.

C05) How do I work around "Labeled imperative not implemented"?

If you want to write:
   (L: Imp1; Imp2; ... Impi :L)
(which is not implemented), you should instead write:
   L: (# do Imp1; Imp2; ... Impi #)
In fact, the (L: ... :L) construct is being considered for exclusion from the BETA language due to the very simple replacement shown above.

See also L22.

C06) Why does a BETA program called cause problems on some UNIX installations?

By default, the executable generated from a BETA program called is called test. Depending on your UNIX installation's defaults and your own environment variables, attempts to execute the BETA program by typing test may, however, result in the standard system program test being executed instead. To avoid the problem, just type ./test instead of test.

Similar problems can arise with other, existing UNIX commands.

[Note: This is a typical beginner's problem, not related to the BETA language or the BETA environment as such.]

C07) How do I disable qualification check warnings?

The "A run-time qualification check will be generated here" warning may be disabled by using compiler switches. In version v5.0 of the compiler, you can use the -noquawarn (or -q) switch. All warnings may disabled by using the -nowarnings (or -w) switch. If you would like the -q option to become the default, you can include it in your BETAOPTS environment variable, e.g.
   setenv BETAOPTS -q
If you would like to temporarily turn qualification check warnings back on, you may then do so by specifying the -quawarn switch.

As of version v5.1 of the compiler, the switch -noquawarn have been renamed to --noWarnQua, and the switch -quawarn have been renamed to --warnQua.

C08) What is the difference between P and &P?

Consider the following BETA program:
   (# P: (# do ... #)
   do P; &P
Compiling this program with the current BETA compiler shows no difference in the code generated for P and &P.

However, the semantics of BETA defines a difference, namely that P is the execution of an inserted item and that &P is the creation and execution of a dynamic item, one of the differences being that inserted items are only allocated once, irrespectively of how many times they are executed.

The current BETA compiler implements inserted items as dynamic ones, thereby not taking advantage of the potential possibility for optimization. This limitation will be removed in a future release of the compiler.

C09) What does "virtual prefix not implemented" mean? [corrected in r4.0]

A couple of typos in the compiler manual [MIA 90-02(1.3) August 1994] for version v5.0 of the compiler have caused some confusion over this message. Section 5, item 8 ("Implementation Restrictions") should read as follows:
8. Virtual superpatterns, i.e.,
   A::< (# ... #); (* where A is some virtual *)
   B: A(# ... #);
have not been implemented.

By using a final binding, this limitation can often be overcome like this:

   A:: (# ... #); (* A is no longer virtual *)
   B: A(# ... #);
The situation may also occur in a more indirect way:
     (# node:< (# ... #);
        nodeList: @list(# element::< node #);
Here the virtual further binding of element in list is not allowed, since node is itself virtual.

The next version of the compiler will allow final binding using a pattern that is itself virtual. That is, you will be allowed to do this:

     (# node:< (# ... #);
        nodeList: @list(# element:: node #);
In version 5.0 of the compiler, this situation is not handled correctly. Instead you can do as follows:
     (# node:< (# ... #);
        nodeListElement: (# n: ^node enter n[] exit n[] #);
        nodeList: @list(# element::< nodeListElement #);
General virtual prefixes behave much like multiple inheritance and will not be implemented in the near future.

These errors have been fixed in the manual for the version v5.1 of the compiler.

C10) What should I do if the compiler prints "Please report the error to Mjølner Informatics" and stops?

The compiler may under very rare conditions run into an error from which it is unable to recover. It will often print out the message "Please report the error to Mjølner Informatics" just before stopping. If you run into an error like this, you should do the following:

  1. Check in question C11, that the error has not yet been reported.
  2. If it has not been reported, please make an archive with the following files (using e.g. tar on UNIX, and e.g. StuffIt or CompactPro on macintosh): Then please mail this file to with a short description of the error.
For users of r4.0, you will find a new tool, betatar, which is usefull for packing the entire set of source files into a tar-file (only available on UNIX platforms)

C11) What are the known errors in v5.0 of the compiler?

The following paragraphs deals with various bugs and workarounds in the different compiler versions.

C11.1) Bugs in version 5.0 of the compiler

Since the release of v5.0 of the compiler in august 1994, the following errors have been reported.

Some of these errors occur in very specific situations, that are hard to describe in general, but others may be generally presented, please see below.

C11.1.1. Static Constants [fixed in v5.1]
The following program will make the compiler crash:
   ORIGIN '~beta/basiclib/current/betaenv';
   --- program: descriptor ---
   (# E: @(# exit 1 #) #)
The compiler reports:
   ******* System error!!!
   Constant used as static item
   Please report this error to Mjolner Informatics
and then stops.

This is because constants should be declared without the '@' sign, i.e.:

   ORIGIN '~beta/basiclib/current/betaenv';
   --- program: descriptor ---
   (# E: (# exit 1 #) #)
C11.1.2. Computed remotes and virtuals [fixed in v5.1]
The computed remotes, that the compiler supports in general from release v5.0, will sometimes make the compiler crash, especially if virtuals are involved. Example:
   ORIGIN '~beta/basiclib/current/betaenv';
   INCLUDE '~beta/containers/current/list';
   --- program: descriptor ---
   (# point: (# x: @integer; #);
      pointList: @List
        (# element::point;
           headx: (# exit (head).elm.x #);
This program makes the compiler crash with the error:
   ******* System error!!!
   Pre is empty/null(virtual binding)
   Please report this error to Mjolner Informatics
The workaround in this case is to avoid the computed remote in headx:
   ORIGIN '~beta/basiclib/current/betaenv';
   INCLUDE '~beta/containers/current/list';
   --- program: descriptor ---
   (# point: (# x: @integer; #);
      pointList: @List
        (# element::point;
           thehead: ^theCellType;
           headx: (# do head->thehead[]; exit thehead.elm.x #);
C11.1.3. "T1PROGRAM undefined" reported by the linker [fixed in v5.1]
As explained in section 7.3 "Assembler and Linker Errors" in the compiler reference manual [MIA 90-02], if an unbound SLOT of category Descriptor or Dopart exist in your program, then this is currently not reported by the compiler itself, but will be detected as an "Undefined Entry" by the linker. Especially if you are new to BETA programming, you may wonder why compiling this fragment (
   ORIGIN '~beta/basiclib/current/betaenv';
   --- lib: attributes ---
   foo: (# (* ... *) #);
with "beta foolib" causes the linker error "T1PROGRAM undefined". In this case the reason is that the fragment is actually a library fragment - it only declares attributes to be used by some program. Specifically the PROGRAM descriptor SLOT defined in "betaenv" has not been bound, and thus the error.

The solution is quite simple: Just compile the program as "beta -c foolib" instead. The next version of the BETA compiler will not attempt to do the linking if the PROGRAM SLOT is not bound.

If you think this is strange, compare to the equivalent situation in C (foolib.c)

   foo() { /* ... */ }
If you compile this file with e.g. "cc foolib.c", you will often get the linker error that "_main" is not defined. The solution here is like in BETA: "cc -c foolib.c"

Version v5.1 of the compiler may under rare conditions exhibit the above behaviour, in which case you should use the above workaround, except the the compiler switch -c in v5.1 have been renamed to -x.

C11.1.4. Reference assignment of repetitions [fixed in v5.1]
Consider the following example:
   ORIGIN '~beta/basiclib/v1.6/betaenv';
   ---  program: descriptor ---
   (# P0: (# #); P1: P0 (# #);
      R1: [5] ^P0;
      R2: [5] ^P1;
   do R1[]->R2[]; (*not legal*)
It is not legal to assign a repetition reference to another repetition reference. Unfortunately the compiler does NOT catch this error. The program compiles and gives unpredictable results when executed.

It is possible to have the following assignment

which makes R2 be a copy of R1. But R1 and R2 do not refer to the same repetition.

Note, it is of course possible to have the elemenst of R1 point to the same elemenst as P1:

   (for i: R1.range repeat R1[i][]->R2[i][] for)
It would be possible to extend BETA to allow assigning a reference to a repetion object to another reptition, but there are currently no plans for this.
C11.1.5. Assignment to index variables not checked
The BETA book states that it is not legal to assign to the index variable of a for-imperative as in:
   (for i: 12 repeat ...; 5->i; ... for)
This restriction is currently not checked by the compiler.

Version v5.1 of the compiler still does not check for these assignments.

C11.2) Bugs in version 5.1 of the compiler

Since the release of v5.1 of the compiler ultimo 1995, the following errors have been reported.

Some of these errors occur in very specific situations, that are hard to describe in general, but others may be generally presented, please see below.

C11.2.1) "T1PROGRAM undefined" still reported by the linker
As mentioned in C11.1.3, version 5.1 of the compiler partly fixes the problem of "T1PROGRAM undefined". To be specific, v5.1 of the compiler checks, that the PROGRAM slot is met before initiating a call to the linker.

However, it may fail as follows:

   beta frag1 frag2
if frag1 contains a PROGRAM slot, and frag2 does not, you will get the linker error for frag2: Once a PROGRAM slot has been seen, all fragments subsequently translated will be attempted linked. This error also happens if you invoke the compiler as
   beta -r frag1
and then enters frag2 as second fragment to compile when the repeating compiler asks for it.

Also, if you have declared a Dopart- or Descriptor-slot in one of your files, and do not have a fragment, that binds these slots in any of the files in the dependency graph, then the linker may still fail with an undefined entry for this slot.

See also C11.2.2.

C11.2.2) Other undefined entries (compiler import error) [hpux9pa, nti only] [corrected in r4.0]
I experience errors from the linker concerning undefined entries, and I am sure that all of my slots are bound. What is wrong?

You may have encountered a situation where the internal import tables of the compiler gets confused because two of your slots have identical names.

	ORIGIN '~beta/basiclib/v1.6/betaenv';
	INCLUDE 'foo';
	--PROGRAM: descriptor--
	do foo
	ORIGIN '~beta/basiclib/v1.6/betaenv';
	BODY 'foobody';
	-- LIB: attributes --
	  (# size: (# s: @integer <<SLOT size:dopart>> exit s #);
	  do size -> putint; newline;
	ORIGIN 'foo';
	INCLUDE 'bar';
	-- size: dopart --
	do (&bar[]).size -> s
	ORIGIN '~beta/basiclib/v1.6/betaenv';
	BODY 'barbody';
	--LIB: attributes--
	  (# size: (# s: @integer <<SLOT size:dopart>> exit s #)#);
	ORIGIN 'bar'
	-- size: dopart --
	do 1 -> s
Although somewhat stupid, you would expect this program to print "1" onto the screen. And it does so on most platforms. But on the platforms hpux9pa (HPPA 9000/700 running HP-UX 9) and nti (Windows 95 / 98 / 2000 / Windows NT), when assembling the code produced for foobody, you get an error like
   undefined label - M2BAR
The reason for this, is that the compiler gets confused by the two dopart slots both tagged with "size".

The solution is to use two distinct names, e.g. foosize and barsize. Such a naming scheme is advisable to use in general - notice that if the two SLOTs had been of kind Descriptor, then on all platforms, you would get

   multiply defined: M1SIZE
C11.2.3) Qualification error in code generation of division expression [linux, nti only]
Sometimes v5.1 of the compiler on Linux and Windows 95/98/2000/NT will will crash with a Qualification Error during code generation of expressions involving division.

If the resulting dump file starts with something like

   item <op1ToEBX#> in ~beta/.../system/v5.1/LINUXmachine
   -- GDIV-~ in ~beta/.../system/v5.1/LINUXmachine
then it is this error that has occurred.

On linux, the error will occur if you compile e.g. the demo ~beta/demo/r3.1/Xt/awenv/ None of the demos on Windows NT/95/98/2000 contain expressions that will cause this error, but you may encounter the problem in files of your own.

The solution is to split up the expression involving the division into simpler expressions. Use option --traceCode to find out what expression is causing the error.

C11.3) Bugs in version 5.2 of the compiler

Since the release of v5.2 of the compiler august 1996, the following errors have been reported.

Some of these errors occur in very specific situations, that are hard to describe in general, but others may be generally presented, please see below.

C11.3.1) Strange error messages like "attempting to translate" [corrected in r4.0.1]
Some of the internal restructuring of the compiler that has been done for version 5.2 has caused a new bug to appear. The symptom of the bug is that .bet sometimes gets appended to the file name reported, when e.g. an attempt to write a file fails because of permission problems.

An example is

You are attempting to translate the file
You do not have permission for doing this!
in case the file /users/smith/beta/private/sun4s/foobody..db, or the directory it resides in, is write protected.

There is currently no workaround for this bug, but it is usually obvious what file name should have been reported.

C11.3.2) Errors when evaluating expressions involving reals and external calls [corrected in r4.0.1]
On all supported platforms, using both reals and external (C) calls in an expression may yield unpredictable results.

For instance the following program

ORIGIN '~beta/basiclib/v1.5/math';
--PROGRAM: descriptor--
do (1->sqrt) -> putint; newline;
   (10->log10) -> putint; newline;
   (1->sqrt)+(10->log10) -> putint; newline;
will give the (wrong) output
on Solaris. The only known workaround is to split up the expressions, so that the parts that call the external functions are isolated (like the first part of the above program).

C12) Tracing the work of compiler?

In the extremely rare event that the compiler crashes during compilation of your program, you may yourself do some tracing of the compilation to find out what particular part of your program, that makes the compiler crash. You do this by specifying some compiler switches:
  1. If the compiler crashes during *code generation* of a fragment, please do this:
       beta -s 308 311 0 <file>
    This will make the compiler print out each declaration and imperative just before code is generated for it. Thus when the compiler crashes, you can see what part of your program caused it.
  2. If the compiler crashes during *checking* of a fragment, please do this:
       beta -s 191 192 193 0 <file>
    This will make the compiler print out each descriptor, declaration and imperative just before checking it. Thus when the compiler crashes, you can see what part of your program caused it.

In version v5.1 of the compiler, you can use the two new compiler switches --traceCode and --traceCheck instead.

C13) Problem with floating point expressions in connection with repetitions [fixed in v5.1]

The compiler does not generate correct code when floating point expressions are used in the calculation of repetition ranges as in:
      R: [FR1] ...
   do ...
where FR1, FR2 and FR3 are expressions yielding a floating point value. The compiler should convert these floating point values into integer values, but fails in doing so.

You can get around the error by explicitly converting the expression to an integer value. If "I" is an integer variable, then the following will work:

      R: [FR1->I] ...
   do ...

This problem have been fixed in version v5.1 of the compiler.

C14) New features introduced in the Compiler

C14.1> New features in version 5.3 of the Compiler

BUILD property
BUILD property now included in the BETA compiler. This replaces the use of MAKE.
See the BETA Compiler Manual for more details:
Binary Object Files
The compiler now generates binary object files on Windows95/98/2000/NT. This eliminates the need for an external assembler.
Debug info
The compiler now generates debug info on Win32 platforms. This enables the debugger, Valhalla, to work.
The compiler now supports gnu as SDK. This makes personal use completely free on Win32.
SGI: IRIX 6.x is now supported (see however SG04).

C14.2) New features in version 5.2 of the Compiler

The following new features have been implemented in version 5.2 of the compiler, compared to version 5.1.
New Platforms
Much effort has been put into porting the compiler onto new platforms: This work has caused a lot of changes to the interior of the compiler and runtime system. These changes should, however, be transparent to the user.

## now allowed for objects as well as for patterns
You may now use P## as an alternative to P.struc when P is an object. Previously ## was only allowed for patterns.

$CC set in UNIX job files
The job files on UNIX platforms now set the CC environment variable to a reasonable default value before executing the MAKE commands. Thus $(CC) may now be used in the make files on UNIX platforms.

Check for bound SLOTs
The compiler will now only attempt to link if a PROGRAM slot has been found in the dependency graph (this feature was introduced in v5.1 of the compiler, but the implementation was buggy). If SLOTs of category dopart or descriptor in the dependency graph are not bound, and linking would otherwise have happened, the compiler now issues a warning and does not attempt to link. This is the kind of situation that could give an "Undefined Reference" error at link time in v5.1 (and earlier versions) of the compiler.

Likewise, if two or more fragments try to bind the same SLOT, the compiler will give a warning. This is the kind of situation which could give an "Multiply Defined Symbol" error at link time in v5.1 (and earlier versions) of the compiler.

Interfragment leave/restart
Added support for interfragment leave/restart as in
   ORIGIN '~beta/basiclib/v1.5/betaenv'; 
   BODY 'foobody';
   (# do L: <<SLOT LL:descriptor>> #)
   ORIGIN 'foo';
   (# do leave L #)
This feature did not work in previous versions of the compiler.

Generalized special characters in string literals
The following special characters are now allowed in BETA string literals (some of them, e.g. \t, has worked in previous versions, too):
\a alert (bell) character
\b backspace
\f form feed
\n newline
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\? question mark
\' single quote
\" double quote
\ooo octal number
The \ooo form can be shortened to \o or \oo, provided that the character immediately following it is not a digit.

Note that the backslash character is now an escape sequence which must itself be escaped if used literally. Thus, one must now write '\\' instead of the old-style '\'.

Note that you may now use \' as an alternative to the old-style '' for including literal quotes in a string. Thus, 'Tom\'s Cottage' produces the same result as 'Tom''s Cottage'.

C14.3) New features in version 5.1 of the Compiler

The following new features have been implemented in version 5.1 of the compiler, compared to version 5.0.
General Repetitions
Repetitions of static objects are now allowed. That is, given
   A: (# ... #); V:< A;
   P: (# ... #);
   S: <<SLOT SS:Descriptor>>;
   X:  [10] @P;
   XC: [11] @|P;
   Y:  [12] @V;
   YC: [13] @|V;
   Z:  [14] @S;
   ZC: [15] @|S;
are all allowed. The operators new and extend also applies to repetitions of this kind, like for other repetitions.

Qualification from pattern attributes
It is now possible to qualify a reference as in the following example:
   grammar: (# symbol: (# ... #); .... #);
   A: ^grammar.symbol 
This was previously forbidden because grammar is not an object.

THIS(P) applies to prefix
Previously THIS(P) was only known to work inside the P pattern. Now it also works for prefixes of P, e.g.:
   Q: (# x:  @integer; ... #);
   P: Q(# x: @integer; 
      do ... THIS(Q).x -> ... (* will get the x of Q *)

Short-circuit Boolean Expressions
Boolean expressions are now implemented as short-circuit. That is, B2 is not evaluated if B1 is true in
   B1 or B2
and B2 is not evaluated if B1 is false in
   B1 and B2	

Final Binding to a Virtual Pattern
Final binding of a virtual pattern to another pattern, which is virtual itself, is now allowed. That is, given the following:
   P1: (# V:< ... (* V virtual *)
          W:< ... (* W virtual *)
it is now allowed to do the following in a specialization of P1:
   P2: P1(# W:: V (* V still virtual, but W now final bound *) #);
The implementation of this is somewhat preliminary.

Special Characters in String Literals
The compiler will no longer accept newline, carriage return or file separator characters in string literals, not even if escaped by \. This is to prevent errors that could occur when a string literal was not closed, i.e. a closing quote was forgotten. This kind of error is no longer possible. Of course, \n is still accepted in string literals.

Furthermore literal null-characters \000 in strings will now result in a warning, since this may yield unpredictable results.

MAKE Property Behavior
When specifying a MAKE property for automatic recompilation of external sources, the makefiles which are run are now executed relative to the directory in which the file containing the MAKE property is placed. This simplifies writing of makefiles a lot.

Consistent Command Line Options
The command line options that can be used when activating the compiler have been revised and are now more consistent than previously: most options now have an activating and a deactivating form. Furthermore most options now have a short one-character equivalent for the non-default form. The short options have been chosen so that the character matches the first character in the long form as often as possible. Short options can now be concatenated.

Please inspect chapter 8 of the Compiler manual for details, and please note that a few options have different meanings than previously, e.g. -c now corresponds to --noCode, where it previously corresponded to --noLink.

C14.4) New features in version 5.0 of the Compiler

The following new features have been implemented in version 5.0 of the compiler, compared to version 4.4.2.
Xor Primitive
An xor primitive is now supported as a basic operation on booleans. That is
      b1, b2, b3: @boolean
   do (b1 xor b2)->b3
is now possible.

Simple If
Often, the following if-construct is used
      b: @boolean;
   do (if b//TRUE then
The BETA compiler now supports an extension to the BETA language called simple-if. This extension means that the case selector may be omitted if the evaluation on the left hand side exits a boolean; it will default to //TRUE. That is, the above may be written:
      b: @boolean;
   do (if b then
Labelled imperatives
Labelled imperatives were previously defined in two forms:
   L: Imp;
   (L: Imp1; ...; :L)
The second form has now been removed from the language. Instead, the compiler offers the form
   L: (# do Imp1; ... #)
Note that this form is implemented very efficiently in the case where there are no declarations in the object descriptor.

SECTION IV: The basic libraries

B01) How do you compare text strings in BETA?

Let's assume that we have:
   t1, t2: @text;
returns true if and only if t1 and t2 are equal, and
returns true if and only if t1 and t2 are equal up to differences in case.

B02) How do you read and write text in BETA?

Texts are written onto standard output by:
which writes the string 'hello' on the screen at current cursor position.
also writes a carriage-return.

Integers are written by:


If you want to write onto other text variables (such as t: @text), you can do it by:


Reading texts is equally easy:

reads a line of text from the keyboard, and assigns a reference to the read text to the text reference s (assumed to be declared as s: ^text).

Reading from other texts (e.g. t) is done by:


B03) Why does getInt followed by getLine not necessarily work as expected?

You have to be careful when scanning input entered from the keyboard. For example, if your program has a section of the form
and you enter, say,
then the string returned by keyboard.getLine will be empty because getInt stops scanning immediately after 42 and does not consume the (non-numeric) new-line character. [Thus, entering
works correctly.] You may insert the line
   (if keyboard.peek=ascii.newline then keyboard.get if);
between the calls to getInt and getLine to get the desired effect, or even call
in which case, however, you won't be able to enter a string starting with white-space characters, similar to the functionality of C's library function scanf().

B04) What is the rationale behind the Mjølner System file directory structures?

This entry describes the file structure of the Mjølner System. The entry is intended as an illustration of one efficient way to structure the files of a BETA development project. At the same time, this file structure is used all over the existing Mjølner System to structure the various subsystems of the Mjølner System.

Let us assume that the development project is called odin, and that it consists of (at least) three subprojects, called brage, vidar, and vale.

We would then define the following file structure (brage/ indicates that brage is the name of a subdirectory):

   odin --+-- brage/
          +-- vidar/
          +-- vale/

Each of the three subprojects may exists in different versions, reflecting the development history. These versions are kept in separate subdirectories for each subproject. Let us illustrate with vidar (having versions 1.0, 1.1, and 1.2):

   vidar -+-- v1.0/
          +-- v1.1/
          +-- v1.2/
A configuration of odin now consists of the combination of the corresponding versions of the subprojects.

Each version of each subproject has the following directory structure (here illustrated with the 1.1 version):

   v1.1 --+--
          +-- ...
          +-- private/
          +-- demo/
          +-- test/
          +-- (* ast files *)
          +-- (* code directories *)

The files contain the public interface files for the v1.1 version of the subproject.

The private subdirectory contains the implementation fragments for the interface files (see later).

The demo subdirectory contains demo programs illustrating the usage of this subproject.

The test subdirectory contains programs for testing the functionality of this subproject.

The (* ast files *) indicates that there will be an Fi.ast file (or an Fi.astL for Intel-based systems) for each, containing the abstract syntax tree (AST) representation of the

The (* code directories *) indicates that there will be one subdirectory for each machine type. Currently, the possible subdirectories are: sun4s, sgi, hpux9pa, ppcmac, nti, and linux. There may be one subdirectory of each machine type.

The substructure consisting of (* ast files *) and (* code directories *) is shared by ALL directories, containing compiled BETA source files, and will therefore not be mentioned further below.

The demo and test subdirectories may be further structured, possibly with a subdirectory for each interface file Fi, but may also follow different layouts.

The private subdirectory is divided into the following substructure:

   private -+--
            +-- ...
            +-- external/
            +-- (* ast files *)
            +-- (* code directories *)
where contains the implementation fragments for the interface files.

The files may be machine-independent implementations or machine-dependent implementations. The files therefore follow the following naming convention:
is the name of a machine-independent implementation
is the name of a machine-dependent implementation(here for macintosh)
In most cases, there exists one implementation file for each interface file, but for large (or complex) interface files, multiple implementation files may exist (apart from the different machine dependent implementation files).

The external subdirectory contains non-BETA source files (such as C source code), and other files which are not used directly by the Mjølner System. The directory structure of external follows the conventions of the non-BETA system used (e.g. the C compiler).

B05) What do the (* idx+ *), etc. comments mean?

At different places in the Mjølner System interface files, you may encounter comments of the form (* idx=2 *), (* idx+ *), or (* idx- *). These are not compiler options - the compiler totally ignores all comments. Instead, the comments are used for formatting the interface files for the documentation. They can be safely ignored.

B06) Error in v1.4/ [corrected in r4.0]

The queue pattern in v1.4/ contains an error that makes the pattern behave like a stack and not a queue. This error is removed in v1.5/

B07) Error in v1.4/ [corrected in r4.0]

The v1.4/ library contains an error that manifests itself by repetition index runtime errors when regexp is used on empty texts. This error will be removed in v1.5/

B08) Error in v1.4/ [corrected in r4.0]

The objectPort pattern in v1.4/ contains an error that makes it almost unusable. This error is removed in v1.5/

B09)Why does my guienvsystemenv program stop at startup?

Possible problems in your program: Your program should look like this:
-- program: descriptor --
(# setWindowEnv:: (# GUI[] -> theWindowEnv[] #);

   GUI: @guienv
     do ... (* open windows here *)
do ... (* fork systems here *)

PART V: Platform Specific Issues

SECTION V: BETA on Macintosh

M01) What are the system requirements to run BETA on Macintosh?

Release 3.1: BETA for Motorola Mac
That is, Release 3.1 runs on machines like Classic II, SE/30, LC, LC II, LC III, Centris, and all Macintosh II, Quadra and PowerBook models (except PowerBook 100). Release 3.1 cannot be used at Mac Plus, SE, and Classic. Release 3.1 works on PowerPC, please look at question M05.
Release 4.0.2 or later: BETA for PowerMac
That is, Release 4.0.2 should work for alle PowerMac models. Please note that, Release 4.0.2 or later does not work on motorola macintoshes.

M02) What is MPW. Where do I get it?

MPW stands for "Macintosh Programmers Workshop", which is the official programming environment for the Macintosh, developed by Apple, Inc. The BETA compiler runs as an MPW tool, that is, it is a command, that can be invoked from the MPW Shell (command interpreter).

You will need MPW 3.4 or later to use BETA. In addition to the MPW Shell, the compiler uses the MPW Link and Rez tools to build the programs.

As of october 1997, Apple has decided to make MPW freely available for downloading. You can download it from

The current versions of the packages needed are Notice!Please notice, that new versions may have been available when you read this.

As an alternative to Apple's MPW, you can use the MPW supported by Metrowerks CodeWarrior. The MWLinkPPC linker included in this commercial package is is up to 10 times faster than PPCLink from Apple.

M03) How do I download MPW from Apple?

To download MPW follow these steps:
  1. Launch 'Fetch 3.0.1'
  2. To make the connection, paste
    in the "New Connection" dialog.
  3. In the menu, choose Customize Post Processing and disable the "Stuffit Archive" post processing options, if there are any. This will allow you to only unpack the items that you need.
  4. Select the "MPW-GM" directory in the file list and Choose Remote Get Directories And Files... in the menu. This will download the entire MPW-GM directory to your disc.
  5. Now you need to unpack the items that are needed. A sit archive are unpacked by dragging it to the "Stuffit Expander" application. You need to unpack the following items:
    1. Interfaces and libraries Unpack: MPW-GM:Interfaces&Libraries:Interfaces:RIncludes.sit.hqx MPW-GM:Interfaces&Libraries:Libraries: SharedLibraries.sit.hqx MPW-GM:Interfaces&Libraries:Libraries: PPCLibraries.sit.hqx
    2. The mpw shell application and workfiles Unpack MPW-GM:MPW:MPW_Shell.sit.hqx This will create a folder named "MPW_Shell.sit.hqx Folder". Move all the items in that folder one level up so they are placed directly in the "MPW-GM:MPW:" folder.
    3. The tools Command ('i' to return to index): Unpack all files in the "MPW-GM:MPW:Tools: " folder.
  6. Rename the MPW-GM to "Development" or some other name not containing a special character (or space). This is needed because there is an error in the Userstartup*beta script concerning spaces in the MPW pathname. You should also give your hard disc a name without special characters.
  7. Set the preferred size of the MPW Shell in the Finder Info to 20 000 k or more.
  8. Drag the UserstartUp*Beta file into the MPW Shell folder. Launch MPW Shell and point out the Beta folder in the dialog that will appear.

M04) Do I need a floating point unit to use BETA?

Yes, to be able to run BETA programs, that use "reals", your machine should have a built-in FPU, *or* you can install an FPU simulator. Several free/shareware FPU simulators are available, e.g. SoftwareFPU, which can be fetched from most macintosh archives, or from the writer, John Neil, at

M05) Does BETA work on PowerPC machines?

As of release 4.0.2, PowerPC based macintoshes are the only macintoshes supported.

Release 3.1 of BETA can be run on PowerMac's using the MC680x0 simulator. That is, the applications will run with the usual slowdown for simulated programs on PowerMac.

M06) Does BETA work on Motorola machines?

Release 3.1 of the Mjølner System is the last supporting Motorola Macintoshes.

As of release 4.0.2, PowerMacintosh is the only Macintosh platform supported.

M07) Known bugs, limitations and inconveniences in release 4.0.2

The current release 4.0.2 is the first for power mac, and is still considered an "alpha release". There are a number of known bugs, limitations and inconveniences:
  1. Link time is very long for BETA programs. We have not been successful in getting appropriate documentation from Apple to make optimal generation of the XCOFF files.
  2. Freja is not yet available for PowerMac
  3. Valhalla is not yet available for PowerMac
  4. bobsit will not work, because the exbobs program did not get ready for r4.0.2
  5. Problems with Sif
  6. Persistence does not work
  7. Check for suspend involving callbacks is not done. If you do a suspend in a callback situation the program is likely to crash.
  8. Integer division by zero will yield unpredictable results (should be caught as an exception as on other platforms).
  9. The pattern doGC in betaenv does not work on ppcmac. This is used in implementation of
    used in the demo
    which consequently does not work
  10. The PutReal pattern in ~beta/basiclib/v1.5/numberio does not work. This is used in the demo programs in
    which does not produce a correct output.
  11. The touch and modtime.set operations on diskentry does not work
  12. The iget operation on keyboard is not implemented. This is used in the demo programs in:
    which consequently does not work
  13. Systemenv is not implemented
  14. Process is not implemented
  15. Bifrost is not implemented
  16. Frigg is not available, due to some problems (Will be fixed in the next release).
  17. There is a number of problems with GuiEnv:
  18. The "Commando BETA" command in the Beta menu, does not work
  19. the new timedate library does not work (linker error).

M08) Known bugs, limitations and inconveniences in release 4.1

M08.1) Why do I get a linker warning about errno?
There is two macintosh libraries that contains errno: StdCLib and OTXTILib - hence the warning. OTXTILib only is used if you include the process or distribution library. This warning can safely be ignored.
M08.2) How do I open a PersistentStore in psbrowser on the macintosh?
You have to move the psbrowser application into the directory that contains the persistentstore you want to open before launching psbrowser. Now you can open the persistentstore via the open command in the file menu. Be aware that the program that generated the persistentstore must call persistentstore_fullnamepatch included from
M08.3) Why does my systemenv program not work as expected in MPW?
If you link a systemenv program as a MPW tool, the keyboard will block all systems when you call any of the get operations: getLine, getInt etc. The solution is to link your program as an application.
M08.4) OpenGL
OpenGL does not work on Apple.

M09) I cannot compile Beta programs with MPW that ships with CW Pro 2.

The problem is caused by a reorganization of the files in

A solution would be to replace the RIncludes folder with an older version.

If you have CW Pro 1, you can grab the Rincludes in the 'CodeWarrior MPW:Interface&Libraries:Interfaces:' folder on that disc. Otherwise, a compatible version of Rincludes can be downloaded from terfaces&Libraries/Interfaces/

SECTION VI: BETA on Windows 95, 98, 2000 and Windows NT

W01) What are the system requirements to run BETA on Windows 95, 98, 2000 and Windows NT?

For more information, see W02.

W02) SDK Requirements for Windows 95, 98, 2000 or Windows NT

In order to use the Mjølner System you need to have an assembler, a linker, a make utility and C libraries from Microsoft or Gnu. The Microsoft utilities are recommended.

These utilities must satisfy the following:

  1. Microsoft
    Starting from release r4.0.1, no assembler is needed any longer.

    For older releases (e.g. r4.0) an assembler is needed. You can install one of the following

    • MASM386.EXE and EDITBIN.EXE from the Microsoft WIN32SDK.
    • ML.EXE, which can be bought as a separate tool from Microsoft. ML.EXE is also part of Microsoft Development Network MSDN (level 2) and the Windows NT 3.5.1 DDK.
    • LINK.EXE from e.g. Microsoft Visual C++.
    • NMAKE.EXE from e.g. Microsoft Visual C++.
      If you do not plan to use the BETA MAKE facility, you can do with a dummy NMAKE program, that simply exits 0.
    C libraries:
    • from e.g. Microsoft Visual C++.
    If you have installed Microsoft Visual C++ 2.0 or later for Windows 95, 98, 2000 or Windows NT, you do not need any more software to run the Mjølner System. If you do not have Visual C++, you will have to get a linker and C libraries from Microsoft (
  2. Gnu.
    No assembler is needed.
    gcc and ld.
    The Gnu make utility.
    C libraries:
    The C libraries that come with gcc for Win32.
You can purchase these utilities from Microsoft ( Please contact their national representatives for ordering information.

W03) Why do I need a MAKE facility?

I do not have a MAKE facility on my Windows 95/98/2000/NT machine. Why do I need that - I thought that the BETA compiler analyzed the dependencies itself?

The BETA compiler keeps track of dependencies between all involved beta files. However, if you want to link in object files generated by an external C compiler og assembler, you may add a MAKE property to make the BETA compiler invoke the make-facility to keep the external objectfiles up-to-date (see section 2.4 in "The Mjølner System - Using on Windows 95 / Windows NT [mia94-32]).

If you do not use the MAKE property in your programs, in principle you do not need a make facility. But since a few of the standard libraries included in the Mjølner System contains such MAKE properties, you will need a make-facility anyway. However, since all external object files in the standard libraries are up-to-date when distributed by Mjølner Informatics, you can do with a dummy make-utility.

For instance you may create a C file like this:

compile it with your C compiler, and install it in your path with the name NMAKE.EXE (if you use the Microsoft SDK).

W06) Known bugs, limitations and inconveniences in release 4.0.2

  1. Most parts of systemenv are still not implemented. Most of the demos in demo\basiclib\systemenv fails. Specificly using the operation "keyboard.get" will block.
  2. Process and socket communication is currently NOT supported. It may work, but known errors exist in these modules. These modules have been scheduled for re-structuring. It is possible, though not likely, that the interface specification changes.
  3. Binary/ASCII files has a work-around (kluge) to compensate for a bug(?) in Windows NT/95/98/2000. If a text file with UNIX style EOL characters (\n) is opened as a text file the offset (ftell) of the first character in the file is the negative of the number of '\n's found in the first 512 bytes. The kluge is that if a file is opened as a text file and a '\n' (UNIX EOL) is found before '\r\n' (Windows NT EOL) it will be opened as a binary file.
  4. File time stamps have proven difficulties in BETA on Windows NT. We (at GMT+1) experience the problem that files are reported to have a timestamp one hour less than the real time stamp of the file. This also means that when touching a file entry the file will be touched with a wrong time stamp (in our case one hour later than the real time).
  5. Freja is not available for nti
  6. Valhalla is not available for nti
  7. The new timedate library does not work (linker error).

W07) Known bugs, limitations and inconveniences in release 4.1

  1. Some parts of systemenv are still not implemented. Some of the demos in demo\basiclib\systemenv fails. Specificly using the operation "keyboard.get" will block the entire process, not only the component issuing the call.
  2. Binary/ASCII files has a work-around (kluge) to compensate for a bug(?) in Windows NT/95/98/2000. If a text file with UNIX style EOL characters (\n) is opened as a text file the offset (ftell) of the first character in the file is the negative of the number of '\n's found in the first 512 bytes. The kluge is that if a file is opened as a text file and a '\n' (UNIX EOL) is found before '\r\n' (Windows NT EOL) it will be opened as a binary file.
  3. File time stamps have proven difficulties in BETA on Windows NT. We (at GMT+1) experience the problem that files are reported to have a timestamp one hour less than the real time stamp of the file. This also means that when touching a file entry the file will be touched with a wrong time stamp (in our case one hour later than the real time).
  4. Freja is not available for nti
  5. BETACC.EXE misplaced on CD:

    The program BETACC.EXE is misplaced on the CD distribution of release 4.1
    BETACC.EXE is used by the compiler when compilation of c-files is required, eg. when beta-programs use the BUILD directive/external pattern.
    On the CD BETACC.EXE is placed in BETALIB but should be moved to BETALIB\bin. eg.



HP01) What are the system requirements to run BETA on HPUX workstations?


HP02) Why do some callbacks cause "Illegal Instruction" on hpux9pa (using v5.0 of the compiler)?

If the following program is compiled and run on an hpux9pa (HP series 700 HPPA, HP-UX 9.x) using the BETA compiler version v5.0), it displays a window with the text "Timer" in it, prints a random number of 7'digits on the screen, and then dies with "Illegal Instruction":
   ORIGIN '~beta/Xt/v1.8/awenv';
   --- program: descriptor ---
   (# l: @Command
        (# init:: (# do 'Timer'->label #)#);
      t: @Timer
        (# timeOut:: (# do 10->start; '7'->Put; #) #);
   do l.init;
The reason for this, is that in v2.6 of the hpux9pa runtime system for BETA there is an error, which occurs if a callback is called very soon after it is installed. In this case it is called ~10 ms after being installed, and almost no other code has been executed in this period of time. In this situation an HPPA cache should have been flushed to ensure the correct behaviour, but there was an error in the runtime system delivered with release 3.0 of the Mjølner System. The solution is to acquire a patched runtime system from Mjølner Informatics.


Lx01) What are the system requirements to run BETA on Linux machines?

In lack of Motif libraries, you can use the Lesstif Motif clone. These libraries works acceptable, but they are not 100% stabil. See BETA-LESSTIF-FAQ

Lx02) How to make the BETA compiler version 5.0/5.1 work with Linux ELF libraries [corrected in r4.0]

If you are using a Linux version with support for the ELF libraries, the Mjølner System (release 3.1) cannot be used immediately. You will have to introduce the following patch:
  1. Make sure that /usr/lib/crt0.o can be found. E.g. do this:
       pushd /usr/lib; ln -s /usr/i486-linuxaout/lib/crt0.o; popd
  2. Make sure the linker is called with "-m i386linux", either by adding
       LINKOPT linux '-m i386linux';
    in the top of basiclib/v1.4/private/, or (preferable) by adding this in your .bashrc (or the corresponding stuff in your .tcshrc):
       export BETALINKOPTIONS='-dc -dp -X -m i386linux';
    The BETALINKOPTIONS environment variable sets *all* options to the linker, that is why you have to set the other stuff in the variable too.
Disclaimer: This has not been tried with the Motif libraries, but it ought to work.

Thanks to Erik Ernst <> and Stephen J Bevan <> for their investigations on this subject.

Lx03) Why does GuiEnv demos segmentation fail? [error in r4.0 & r4.0.1]

With some Linux distributions, the demos in $BETALIB/guienv/v1.4/demos (aka BETALIB/demo/guienv) all fail with a segmentation fault upon startup, whereas, e.g. the MotifEnv demos all work correct.

The reason for this seems to be a buggy gcc used for producing some of the files in the BETA releases r4.0 and r4.0.1. This was done at the time that the Linux community was switching towards ELF binaries, and possibly this is the reason, that gcc produced wrong files. The problem has not been observed for release 4.0.2.

A workaround is to do the following (as the owner of BETALIB):

        cd $BETALIB/guienv/v1.4/private/X11
        chmod -R u+w .
        rm linux/guienv_unix.o
        rm linux/Canvas.o
        rm linux/Button.o
        rm linux/IconButton.o
        rm linux/ToggleButton.o
        beta guienv_unixbody
        chmod -R a-w .

  • Lx04) Using the Mjølner System with RedHat 5 and other glibc 2 based Linux-systems.
  • This is intended for people using the Mjølner System, release 4.1, with RedHat 5 and other glibc 2 based systems.
    What are the symptoms of the problem:
    1. The linking phase of the compiler fails.
    2. The tools (Sif, Frigg, ..) will not start: they core-dump immediately.
    To correct the problems, do the following four steps:
    1. Set the enviroment variable libXm_PATH: libXm_PATH should refer to the directories where the libXm libraries are loacated. If you use the lesstif package included on the Mjølner System r4.1 CD-ROM then it should be:
      e.g. /usr/local/lesstif/lib. If you use a motif or another lesstif installation then point it to where the libXm libraries are installed.
    2. Create two empty object files crtbegin.o and crtend.o and place them inside /usr/lib/. You can do it in the following way:
      	echo "manmathan1 () {}\n" > crtbegin.c
      	echo "manmathan2 () {}\n" > crtend.c
      	gcc -c crtbegin.c crtend.c
      	mv crtbegin.o crtend.o /usr/lib/
    3. Set the enviroment variable BETALINKOPTIONS to:

         -L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ -dc -dp -Bstatic -X
      From bash:
          export BETALINKOPTIONS="-L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ -dc -dp -Bstatic -X"
      From tcsh:
          setenv BETALINKOPTIONS="-L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ -dc -dp -Bstatic -X"
    4. Edit the two environment configuration scripts located in the ~beta/configuration folder by commenting out the LD_LIBRARY_PATH settings by typing a #-sign in front:
      in, line 171
      in env.csh, line 190
    Please email any problems to:

    SECTION IX: BETA on Silicon Graphics

    SG01) What are the system requirements to run BETA on Silicon Graphics workstations?

    If you run IRIX 5.3, you must have installed patch 410 from SGI in order to fix the linker to generate pure ELF binaries. If you have not applied this patch, the linker will fail like this:
            Unknown flag: -woff

    SG02) Gnu C Compiler gcc not supported

    You cannot link applications, that specify external OBJFILEs compiled with gcc. You must use cc for external object files. If you get an error like:
            ld: FATAL 2: Internal: at ../commonlib/ld3264/relocate.c \
            merge_ext returns nil during relocation
    this may be caused by an attempt to link a gcc-produced file into your application.

    If you use make files invoked via the MAKE property in a BETA fragment, you should use $(CC) instead of a hardcoded C compiler name. The BETA compiler sets CC to a proper default value on alle UNIX platforms.

    If you do not know which external object file caused the error to happen, you may find out like this:

    1. Compile the program with beta -p. This will preserve the job-file, containing the link-directive(s) for the program.
    2. Open the preserved jobfile in a text-editor. The job-file is located in the sgi subdirectory, and has the same name as the application, but with ..job appended.
    3. Add -v as argument to the last invocation of /bin/ld in the job file.
    4. Save and execute the job-file.
    When the job-file starts to link the final application, it will now print out the name of each file in the last link-directive as they are processed. This includes all external object files (specified by OBJFILE in the BETA code), and you should thus be able to see what file causes the linker to fail: It is likely to be the last one printed out before the linker crashes.

    SG03) Remember to set LD_LIBRARY_PATH

    After linking shared objects, the LD_LIBRARY_PATH should be set so that it includes the directory, where the shared object files reside. The compiler will tell which directory this is. If you get an error like:
            793:./foo: rld: Fatal Error: cannot map soname 'foo1..gso' \
            using any of the filenames /usr/lib/foo1..gso:/lib/foo1..gso:\
            /lib/cmplrs/cc/foo1..gso:/usr/lib/cmplrs/cc/foo1..gso: \
            -- either the file does not exist or the file is not mappable \
            (with reason indicated in previous msg)
    when running you application (here foo), this may be caused by LD_LIBRARY_PATH not being set correctly.

    SG04) Using BETA on IRIX 6 machines

    On the newest Silicon Graphics OS, IRIX 6, three binary object file formats are supported by the OS - old 32 bit format, new 32 bit format and new 64 bit format. The BETA compiler in release 4.1, however, only supports the old 32 bit format - the format also used for IRIX 5.

    There are 3 implications of this:

    1. Link directive:
      The compiler automatically fixes the link directive on IRIX 6 machines
    2. Using BUILD:
      If you are using BUILD properties, and may thus need to invoke the C compiler, please note that you have to specify the CC environment variable before compiling your BETA program:
        setenv CC 'cc -32'
      If you are compiling with beta -d ..., you may also set CC like this:
        setenv CC 'cc -O2 -32'
      In a future version of the compiler, this will be done automatically.
    3. LD_LIBRARY_PATH specification:
      If your program is linked using shared object files (the compiler will tell you so), as always, you should set LD_LIBRARY_PATH to point to the directory, where the shared object files are places (usually directory sgi). Since the compiler uses old 32 bit object files, it is enough to set LD_LIBRARY_PATH. That is, do not set any of the new LD_LIBRARYN32_PATH or LD_LIBRARY64_PATH variables. If you need to set any of these, then all 3 variables should be set, and the sgi directory should be included in all three.

    SG05) Limitations, bugs and inconveniences

    SG05.1) Limitations
    The following limitations are currently specific to the SGI implementation:
    1. Lazy Fetch in persistence is not implemented. (everything is fetzhed.) This means that the following demos does not work as intended:
    2. Check for suspend involving callbacks is not done. If you do a suspend in a callback situation the program is likely to crash.
    3. Integer division by zero will yield unpredictable results (should be caught as an exception as on other platforms). [corrected in r4.1]
    4. The compiler may sometimes crash during code generation. Normally you can just restart the compilation in this case. [corrected in r4.1]
    5. There is sometimes a problem with real expressions involving external calls. This is e.g. the case in the demo
      which currently does not work on sgi. [corrected in r4.1]
    6. The following runtime errors may not always result in correct dumps:
               Repetition subrange out of range
               Text parameter to C routine too big (max. 1000 bytes)
    7. Do not specify an output file in the sgi-directory to the compiler. I.e. do not do this:
                beta -o sgi/foo
      Instead you should do this:
                beta -o foo
                mv foo sgi/
      The first method may fail when linking shared. The problem is, that the shared object files are renamed to the file sgi in the sgi directory, and thus the program will fail to execute. [corrected in r4.1]
    SG05.2) doGCand scanobjdoes not work
    The pattern doGC in betaenv does not work on SGI. This is used in implementation of
    used in the demo
    which consequently does not work.
    SG05.3) About ld: WARNING 56: Invalid warning number (133)
    When the beta compiler is used on IRIX 5.3 it may give the warning ld: WARNING 56: Invalid warning number (133) at link time. This warning is caused by the compiler trying to turn of an IRIX 6.2 warning (number 133), which does not exist on IRIX 5.3. The warning can be safely ignored.
    SG05.4) About ld: WARNING 85: definition of vendorShellWidgetClass...
    When compiling awenv programs on SGI, the linker will give the following warnings:
    ld: WARNING 85: definition of vendorShellWidgetClass in /usr/lib/
    preempts that definition in /usr/lib/
    ld: WARNING 85: definition of vendorShellClassRec in /usr/lib/
    preempts that definition in /usr/lib/
    These warnings are caused by (intentional) overriding of the X Toolkit VendorShell in the SGI athena libraries. The warnings can be safely ignored.

    SG06) Disclaimer (Slow startup of tools)

    Startup time for SGItools(compiler, frigg, sif, psbrowser, ...) are quite significant. This is due to the dynamic linker, and may be fixed in a future version.

    SECTION X: BETA on Sun workstations

    Sun01) What are the system requirements to run BETA on Sun workstations?

    Sun02) Running BETA on Solaris v2.6 and later

    Release 4.1 needs a patch to run on Solaris 2.6. Download it here, and install it on top of the basic release.
    Jørgen Lindskov Knudsen / Aarhus University /