Please send corrections, additions and comments to Jørgen Lindskov
Knudsen (jlk@cs.au.dk
).
This information is abstracted and condensed from the posts of many different contributors. No guarantees are made regarding its accuracy.
:<
, ::<
, and ::
)?
INNER
?
beta-mode
for Emacs exist?
"*****Only pattern-declarations may appear in a fragment of
category 'attributes'"
?
INCLUDE
facilities of BETA and C?
inner
in a body
fragment?
There must be only one non-shell widget which is son of Toplevel
"?
"A run-time qualification check will be inserted here"
?
"*****Repetition of non simple patterns is not implemented"
? [corrected in r4.0]
"Labeled imperative not implemented"
?
test.bet
cause problems on some UNIX installations?
P
and &P
?
getInt
followed by getLine
not necessarily work as expected?
(* idx+ *)
, etc. comments mean?
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.
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.
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 InformaticsHelsingforsgade 27
DK-8200 Aarhus N
Denmark
Phone: +45 70 27 43 43
Fax: +45 70 27 43 44
E-mail:info@mjolner.com
WWW:http://www.mjolner.com
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.
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: http://troubadix.physik.tu-berlin.de/~petz0433/beta/eindex.html.
Ole Lehrmann Madsen, Birger Møller-Pedersen, Kristen Nygaard:An german introduction to BETA can be found in the book:
"Object-Oriented Programming in the BETA Programming Language"
Addison-Wesley and ACM Press, 1993
ISBN 0-201-62430-3
Ernst Erich Doberkat, Stefan Dißmann:The Mjølner System and the BETA language is also extensively described in the book:
"Einführung in die objectkorientierte Programmierung mit BETA"
Addison-Wesley-Longman, 1996
ISBN 3-8273-1026-1
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
Besides, various current activities indicate that introductory material in the form of tutorials are in the pipeline.
See also question Q08.
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.
Postings to comp.lang.beta are automatically forwarded (moderated) to the usergroup@mjolner.com mailing list and mails to the mailing list is automatically posted to the newsgroup.
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.
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 Linux.com).
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).
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.
https://beta.cs.au.dk/mjolner_system/download.html
olm@cs.au.dk
) 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
DeltaIn 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
GammaIn 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
BETAFinally the machine level languages were referred to as
AlphaLong 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
Epsilonwas 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.
lgrind
LaTeX package.
You can use the following lgrind
style:
beta|the BETA programming language:\ :pb=(^\d?\p\d?\:\d?\p?\d?\(#\d?:\ :id=_:\ :bb=\d(\(#|\(if|\(for)\d:\ :be=\d(#\)|if\)|for\))\d|;:\ :oc:\ :cb=\(*:\ :ce=*\):\ :sb=':\ :se=':\ :tb=%%:\ :te=%%:\ :mb=%\$:\ :me=\$%:\ :vb=%\|:\ :ve=\|%:\ :kw=if then else for repeat\ do inner none this enter exit leave restart suspend\ and or xor mod div\ stop:This
lgrind
style can be made available in two different ways:
lgrind
styles. This
is done by copying the above definition into the
lgrindefs
styles file, which is installed as part of the
lgrind
installation (possibly in the
/usr/share/local/lib/lgrindefs
file - dependent on your
local setup). This installation must be done by the local systems
administrator.
lgrind
style onto a file in
your personal file system. Let us for further reference assume that this file is called: $HOME/lgrind/lgrindefs
.
lgrind
stylelgrind
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
prog.bet
.
lgrind
style is saved among the standard
lgrind
styles, you execute:
lgrind -lbeta -i prog.bet > prog.tex
lgrind
style is saved in your personal file
system, you execute:
lgrind -lbeta -d $HOME/lgrind/lgrindefs -i prog.bet > prog.tex
\usepackage{lgrind}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:
\lgrindfile{prog}
\lagrind[htbp]{prog.tex}{caption}{label}
lgridfile
or lagrind
command
for each piece of BETA source code, you wish to include in the
document.
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
https://beta.cs.au.dk/mjolner_system/beta.html
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.
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.
Xor
Primitive xor
primitive is supported as a basic operation on
booleans. That is b1, b2, b3: @boolean do b1 xor b2 -> b3is possible.
B1 or B2
B2
is not evaluated if
B1
is true
, andB1 and B2
B2
is not evaluated if B1
is false
.
L: Imp;and
(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
).
:<
, ::<
, and ::
)?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:
INNER
?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
inner
s 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
.
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##; ©Type[]->theCopy[]; (* 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 *) copy::< (# 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 *) copy::< (# 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;then
a.copy->aCopy[]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.
olm@cs.au.dk
) 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:
A: (# V:< A1; ... do ... inner ... #); B: A(# V::< A2; ... do ... inner ... #); C: A(# V::< A3; ... do ... inner ... #); D: B & C (# V:: A4; ... do ... #);(The syntax
B & C
has tentatively been used for MI in BETA.)
Here A2
and A3
must both be subclasses of
A1
, and A4
must be a subclass of both
A2
and A3
.
(In her Ph.D. Thesis, Kristine Thomsen defined a language
along these lines, which handled virtual bindings a la those in BETA.
It should be available from the Computer Science Department, Aarhus
University.)
inner
s of multiple superclasses
must also be defined.
In the example above, should B
's do-part be executed
before C
's or vice versa?
Since we are not in favour of making the order of superclasses
significant, we were considering letting the execution order of
B
and C
be non-deterministic, in the sense
that the implementation may execute B
or C
in any order.
(Thomsen's thesis also deals with combing inner
s and
proposes a number of other alternatives.
You may also want to take a look at:
K. S. Thomsen: "Inheritance on Processes, Exemplified
on Distributed Termination Detection", International Journal
of Parallel Programming, pages 24-37, November 1988.)
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:
Window / \ WindowWithBorder WindowWithTitle \ / WindowWithBorderAndTitleIn BETA this may be handled using block-structure
Window: (# ... 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.
olm@cs.au.dk
) 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-imperativeWe 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
https://beta.cs.au.dk/Manuals/latest/beta-intro/Quick-Reference-Card.html
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; do 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 *) #)
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:
(7,17)->&multiply->&putInt;
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; e->content[currentSize]; #); empty: (# exit (currentSize=0) #); pop: (# e: @integer; do content[currentSize]->e; currentSize-1->currentSize; 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:
V
was declared in P
(or some superpattern
of P
) as V:< Q
,
and Q1
is a direct or indirect subpattern of
Q
.
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
.
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.
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 External
s are case-sensitive (due to
identifiers in the C programming language being case-sensitible).
Please refer to the BETA Compiler Manual for details:
https://beta.cs.au.dk/Manuals/latest/compiler/
A BETA indentifier has to start with a letter or '_', and may be followed by a sequence of letters, digits, and '_'.
restart idwhere 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).
and
leave 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.Example:
(# 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); '+'->put #); do P #)will give the following output:
[1+][2-][3*4+][5+]
<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.
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.
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.
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.
https://beta.cs.au.dk/Manuals/latest/basiclib
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:
https://beta.cs.au.dk/Manuals/latest/basiclib
https://beta.cs.au.dk/Manuals/latest/process
https://beta.cs.au.dk/Manuals/latest/basiclib
container _________________|__________________________ | | | | collection arrayContainer sequentialContainer list ______|_______ ___________|_______________ | | | | | | multiset hashTable stack queue deque prioQueue | | set extensibleHashTable __|_____________________ | | classificationSet classificationSubSetContainer patterns are generic patterns in the sense that the element type of the elements kept in the container can vary between different container instances.
https://beta.cs.au.dk/Manuals/latest/containers
https://beta.cs.au.dk/Manuals/latest/persistence
https://beta.cs.au.dk/Manuals/latest/yggdrasil
system
,
semaphore
, fork
, monitor
,
port
, restrictedPort
, objectPort
,
qualifiedPort
, conc
, and alt
.
guienv
..
beta-mode
for Emacs exist?beta-mode
is in the
public domain and can be obtained by FTP from the directory ftp://ftp.cs.au.dk/pub/beta/emacs
.
The file beta-mode.el
contains a large comment that
explains how to use this.
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.
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
fSource.bet
.
If we want to separate the implementation and the specification, we can make
the following change to fSource.bet
:
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 fBody.bet
:
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).
"*****Only pattern-declarations may appear in a fragment of
category 'attributes'"
?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:
fSource.bet: ORIGIN '...'; BODY 'fBody' --- lib: attributes --- f: (# t: @text; <<SLOT fLib: attributes>> enter t[] <<SLOT fBody: dopart>> #) fBody.bet: 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:
fSource.bet: ORIGIN '...'; BODY 'fBody' --- lib: attributes --- f: (# t: @text; fPrivate: @<<SLOT fLib: descriptor>> enter t[] <<SLOT fBody: dopart>> #) fBody.bet: 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
.
fSource.bet: ORIGIN '...' --- lib: attributes --- f: (# t: @text; <<SLOT fLib: attributes>> enter t[] <<SLOT fBody: dopart>> #) fUsage.bet: ORIGIN '...'; INCLUDE 'fSource' --- program: descriptor --- (# foo: @f do (* ... usage of foo ... *) #) fImpl1.bet: ORIGIN 'fSource' --- fLib: attributes --- i,j: @integer; r: @real --- fBody: dopart --- do (* ... some code implementing f ... *) fImpl2.bet: ORIGIN 'fSource' --- fLib: attributes --- i,j,k: @integer; r, s: @real --- fBody: dopart --- do (* ... some code implementing f ... *) fProg1.bet: ORIGIN 'fUsage'; BODY 'fImpl1' fProg2.bet: ORIGIN 'fUsage'; BODY 'fImpl2'When compiling the
fUsage.bet
fragment separately, it is
impossible to pre-calculate the size of the foo
object, since
foo
will contain i,j,r
in fProg1.bet
,
whereas foo
will contain i,j,k,r,s
in
fProg2.bet
. A solution to this problem is being investigated by Mjølner Informatics, but there are no plan for when this will be supported.
The first problem is a logical problem. Consider:
fSource.bet: ORIGIN '...' --- lib: attributes --- A: (# V:< T; ... #); B: A(# <<Blib: attributes>> ... #); C: B(# V::< T1; ... #) fUsage.bet: ORIGIN 'fSource' --- Blib: attributes --- V::< T2The problem is, that when doing the semantic checking of
V::< T1
in C
, it is impossible to know the further binding in the
fUsage.bet
fragment, since it may be compiled after the
compilation of the fSource.bet
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.
INCLUDE
facilities of BETA and C?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.
inner
in a body
fragment?top.bet: ORIGIN '~beta/basiclib/v1.6/betaenv'; BODY 'testBody' --- lib: attributes --- test: (# do <<SLOT testBody: descriptor>> #) --- program: descriptor --- (# do test(# do ... #) #) testBody.bet: 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
top.bet
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.
(# 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/bobs.bet, 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.
ORIGIN '~beta/Xt/awenv' --- program: descriptor --- AwEnv (# Hello: @Label; do Hello.init; #)whereas the following program creates a window containing "Hello"
ORIGIN '~beta/Xt/awenv' --- program: descriptor --- AwEnv (# Hello: @Label(##); do Hello.init; #)Why?
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.
https://beta.cs.au.dk/Manuals/latest/xwindows
There must be only one non-shell widget which is son of Toplevel
"?ORIGIN '~beta/Xt/awenv'; --- program: descriptor --- AwEnv (# 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:
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.
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
.
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.)
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.
https://beta.cs.au.dk/Manuals/latest/xwindows
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:
byewindow.init; byewindow.popup;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.
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:
13d12 < #include <X11/Xaw/Clock.h> 15,16d13 < #include <X11/Xaw/Logo.h> < #include <X11/Xaw/Mailbox.h> 37d33 < 53,55d48 < 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.
To fix the error have your system administrator change some files:
argList: cStruct (# byteSize::< (# do 100->value #); max: (# exit R.range div 2 #); extend: (# size: @integer; enter size do (if size=0 then R.range->size else size-R.range->size; if); size->R.extend; #); 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. *) cstr->R[number*2-1]; value->R[number*2] #); 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[] #); #);
--- IntegerResourceGet: dopart --- do (1,resourceName, @@value)->private.wargs.set; (Thewidget,private.wargs[],1)->XtGetValues;and
--- AncestorSensitiveGet: dopart --- do (1,xtnancestorsensitive,@@value)->private.wargs.set; (Thewidget,private.wargs[],1)->XtGetValues;respectively.
--- FloatResourceGet: descriptor --- (# status,res: @integer do (1,resourceName,@@value)->private.wargs.set; (theWidget,private.wargs[],1)->XtGetValues; resolution->res; (@@value,res)->getQuotFromFloat->value #)
--- MotifStringResourceGetText: descriptor --- (# S: @MotifString; do (1,resourceName,@@S.value)->Private.Wargs.Set; (TheWidget,Private.Wargs[],1)->XtGetValues; S.getText->t[]; S.destroy; #)and
--- MotifStringResourceGet: descriptor --- (# do (1,resourceName,@@value)->private.wargs.set; (thewidget,private.wargs[],1)->XtGetValues; #)and
--- ProcResourceGet: descriptor --- (# do (1,resourceName,@@p)->private.wargs.set; (Thewidget,private.wargs[],1)->XtGetValues; #)respectively.
--- RowColumnLabelStringGetText: descriptor --- (# S: @MotifString; do (1,resourceName,@@S.value)->Private.Wargs.Set; (TheWidget,Private.Wargs[],1)->XtGetValues; S.getText->t[]; S.destroy; #)and
--- RowColumnLabelStringGet: descriptor --- (# do (1,resourceName,@@value)->private.wargs.set; (thewidget,private.wargs[],1)->XtGetValues; #)respectively.
cd $BETALIB/Xt/v1.8 beta -q -c private/awenvbody.bet motif/private/rowcolumnbody.betto get the changed files recompiled.
sensorLabel: @Label (# init:: (# s: @labelString; t: @MotifString (# init:: (# do ('Sensor:','ItalFont',XmSTRING_DIRECTION_L_TO_R) -> t.setTextSegment; #); #); do (...) t.init; t->s.set; #); #);
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.bet: RowColumn.numColumns motif/texts.bet: TextField.columns Change from IntegerResource to BooleanResource: ----------------------------------------------- awenv.bet: SimpleMenu.menuOnScreen awenv.bet: Paned.refigureMode awenv.bet: AsciiText.autoFill awenv.bet: AsciiText.resize awenv.bet: AsciiText.displayNonprinting awenv.bet: CoreLIB.resizable xtenv.bet: Core.mappedWhenManaged xtenv.bet: Shell.allowShellResize xtenv.bet: Shell.overrideRedirect xtenv.bet: Shell.saveUnder xtenv.bet: WMShell.input xtenv.bet: WMShell.transient xtenv.bet: WMShell.waitForWM xtenv.bet: TopLevelShell.iconic motif/bulletinboard.bet: BulletinBoard.defaultPosition motif/lists.bet: MotifList.automaticSelection motif/scale.bet: Scale.highlightOnEnter motif/texts.bet: ScrolledText.scrollVertical motif/texts.bet: ScrolledText.scrollHorizontal motif/texts.bet: ScrolledText.scrollLeftSide motif/texts.bet: ScrolledText.scrollTopSide motif/texts.bet: TextField.verifyBellThese errors will naturally be corrected in the next release.
"A run-time qualification check will be inserted here"
?-q
or -w
options to the
compiler: "beta -q ..."
or "beta -w
..."
(# Vehicle: (# ... #); Bus: Vehicle(# ... #); aVehicle: ^Vehicle; aBus: ^Bus do ... aVehicle[]->aBus[] ... #)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.
"*****Repetition of non simple patterns is not
implemented"
(using v5.0 of the compiler)? [corrected in r4.0]persons: [100]@person(which is not implemented in version 5.0 of the BETA compiler), you should instead write:
persons: [100]^personsand then, before you start using the
persons
repetition, initialize it by:
(for i: persons.range repeat &person[]->persons[i][] for)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.
"Labeled imperative not implemented"
?(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.
test.bet
cause problems on some UNIX installations?test.bet
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.]
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 -qIf 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
.
P
and &P
?(# 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.
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:graph: (# node:< (# ... #); nodeList: @list(# element::< node #); ... #);Here the virtual further binding ofelement
inlist
is not allowed, sincenode
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:
graph: (# node:< (# ... #); nodeList: @list(# element:: node #); ... #);In version 5.0 of the compiler, this situation is not handled correctly. Instead you can do as follows:graph: (# 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.
betatar
,
which is usefull for packing the entire set of source files into a
tar-file (only available on UNIX platforms)
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.
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 Informaticsand then stops.
This is because constants should be declared without the '@' sign, i.e.:
ORIGIN '~beta/basiclib/current/betaenv'; --- program: descriptor --- (# E: (# exit 1 #) #)
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 InformaticsThe 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 #); #); #)
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
.
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
R1->R2which 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.
(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.
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.
PROGRAM
slot is met before initiating
a call to the linker.
However, it may fail as follows:
beta frag1 frag2if
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 frag1and 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.
Answer:
You may have encountered a situation where the internal import
tables of the compiler gets confused because two of your slots
have identical names.
Consider:
main.bet: ORIGIN '~beta/basiclib/v1.6/betaenv'; INCLUDE 'foo'; --PROGRAM: descriptor-- (# do foo #) foo.bet: ORIGIN '~beta/basiclib/v1.6/betaenv'; BODY 'foobody'; -- LIB: attributes -- foo: (# size: (# s: @integer <<SLOT size:dopart>> exit s #); do size -> putint; newline; #) foobody.bet: ORIGIN 'foo'; INCLUDE 'bar'; -- size: dopart -- do (&bar[]).size -> s bar.bet: ORIGIN '~beta/basiclib/v1.6/betaenv'; BODY 'barbody'; --LIB: attributes-- bar: (# size: (# s: @integer <<SLOT size:dopart>> exit s #)#); barbody.bet: ORIGIN 'bar' -- size: dopart -- do 1 -> sAlthough 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 - M2BARThe 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
If the resulting dump file starts with something like
item <op1ToEBX#> in ~beta/.../system/v5.1/LINUXmachine -- GDIV-~ in ~beta/.../system/v5.1/LINUXmachinethen 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/scroll.bet
.
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.
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.
foo..db.bet
" [corrected in r4.0.1].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 /users/smith/beta/private/sun4s/foobody..db.bet 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.
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
1 1 4on 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).
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.
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
instead.
and
--traceCheck
R: [FR1] ... do ... FR2->R.extend FR3->R.newwhere 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 ... FR2->I->R.extend FR3->I->R.new
This problem have been fixed in version v5.1 of the compiler.
https://beta.cs.au.dk/Manuals/latest/compiler
##
now allowed for objects as well as for patternsP##
as an alternative to
P.struc
when P
is an object. Previously
##
was only allowed for patterns.
$CC
set in UNIX job filesCC
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.
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.
foo.bet: ORIGIN '~beta/basiclib/v1.5/betaenv'; BODY 'foobody'; --PROGRAM:descriptor--- (# do L: <<SLOT LL:descriptor>> #) foobody.bet: ORIGIN 'foo'; --LL:descriptor-- (# do leave L #)This feature did not work in previous versions of the compiler.
\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 |
\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'
.
A: (# ... #); V:< A; P: (# ... #); S: <<SLOT SS:Descriptor>>;then
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.
grammar: (# symbol: (# ... #); .... #); A: ^grammar.symbolThis was previously forbidden because grammar is not an object.
THIS(P)
applies to prefixTHIS(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 *) #)
B2
is not
evaluated if B1
is true
in
B1 or B2and
B2
is not evaluated if B1
is
false
in
B1 and B2
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.
\
. 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 BehaviorMAKE
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.
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
.
b1, b2, b3: @boolean do (b1 xor b2)->b3is now possible.
b: @boolean; do (if b//TRUE then ... else ... if);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 ... else ... if);
L: Imp;and
(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.
t1, t2: @text;Then:
t1[]->t2.equalreturns true if and only if
t1
and t2
are
equal, and
t1[]->t2.equalNCSreturns true if and only if
t1
and t2
are equal
up to differences in case.
'hello'->screen.puttext;which writes the string
'hello'
on the screen at current
cursor position.
'hello'->screen.putline;also writes a carriage-return.
Integers are written by:
7->screen.putInt;
If you want to write onto other text variables
(such as t: @text
), you can do it by:
'hello'->t.puttext; 'hello'->t.putline; 7->t.putInt;
Reading texts is equally easy:
keyboard.getline->s[];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:
t.getline->s[];
getInt
followed by
getLine
not necessarily work as expected?keyboard.getInt->...; ... keyboard.getLine->...;and you enter, say,
42<return> foo<return>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
42foo<return>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
keyboard.scanWhiteSpacein 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()
.
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 --+-- F1.bet | +-- F2.bet | +-- ... | +-- Fn.bet | +-- private/ | +-- demo/ | +-- test/ | +-- (* ast files *) | +-- (* code directories *)
The Fi.bet
files contain the public interface files for the
v1.1
version of the subproject.
The private subdirectory contains the implementation fragments for the
Fi.bet
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
Fi.bet
, containing the abstract syntax tree (AST) representation
of the Fi.bet
.
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 -+-- F1Body.bet | +-- F2Body.bet | +-- ... | +-- FnBody.bet | +-- external/ | +-- (* ast files *) | +-- (* code directories *)where
FiBody.bet
contains the implementation fragments for the
interface files.
The FiBody.bet
files may be machine-independent implementations or
machine-dependent implementations. The FiBody.bet
files therefore
follow the following naming convention:
FiBody.bet
Fi_macBody.bet
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).
(* idx+ *)
, etc. comments mean?(* 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.
queue
pattern in v1.4/seqContainer.bet
contains an error that makes the pattern behave like a stack and not
a queue.
This error is removed in v1.5/seqContainer.bet
.
v1.4/regexp.bet
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/regexp.bet
.
objectPort
pattern in
v1.4/basicsystemenv.bet
contains an error that makes it
almost unusable.
This error is removed in
v1.5/basicsystemenv.bet
.
guienvsystemenv
program stop at startup?systemenv
theWindowEnv
to the
guienv
instance in setWindowEnv
dopart
of
guienv
. You should fork systems in the
dopart
of systemenv
. This might change in a
future release
-- program: descriptor -- systemenv (# setWindowEnv:: (# GUI[] -> theWindowEnv[] #); GUI: @guienv (# do ... (* open windows here *) #); do ... (* fork systems here *) #)
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 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.
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.
As of release 4.0.2, PowerMacintosh is the only Macintosh platform supported.
sysutils/v1.5/scanobjectsused in the demo
demo/sysutils/objinterface/scanobjwhich consequently does not work
~beta/demo/basiclib/reals/and
~beta/demo/basiclib/random/tstgenchi.betwhich does not produce a correct output.
~beta/demo/basiclib/iget/which consequently does not work
errno
?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.
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
~beta/objectbrowser/v1.6/psbrowser/psfullnamepatch
systemenv
program not work as expected in MPW?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.
Interfaces&Libraries:Interfaces:RIncludes:
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
ftp://dev.apple.com/devworld/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./MPW-GM/In terfaces&Libraries/Interfaces/
These utilities must satisfy the following:
For older releases (e.g. r4.0) an assembler is needed. You can install one of the following
Answer:
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:
main() { exit(0); }compile it with your C compiler, and install it in your path with the name NMAKE.EXE (if you use the Microsoft SDK).
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.
move c:\BETA\BETACC.EXE c:\BETA\BIN\BETACC.EXE
ORIGIN '~beta/Xt/v1.8/awenv'; --- program: descriptor --- AwEnv (# l: @Command (# init:: (# do 'Timer'->label #)#); t: @Timer (# timeOut:: (# do 10->start; '7'->Put; #) #); do l.init; 10->t.start; #)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.
/usr/lib/crt0.o
can be found.
E.g. do this:
pushd /usr/lib; ln -s /usr/i486-linuxaout/lib/crt0.o; popd
-m i386linux
",
either by adding
LINKOPT linux '-m i386linux';in the top of
basiclib/v1.4/private/betaenv_unixbody.bet
,
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.
Thanks to Erik Ernst <eernst@cs.au.dk
> and
Stephen J Bevan <bevan@cs.man.ac.uk
> for
their investigations on this subject.
$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 .
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:
<INSTALL_PATH_FOR_LESSTIF>/libe.g.
/usr/local/lesstif/lib
. If you use a motif or
another lesstif installation then point it to where the
libXm
libraries are installed.
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/
BETALINKOPTIONS
to:
-L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -dc -dp -Bstatic -XFrom bash:
export BETALINKOPTIONS="-L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -dc -dp -Bstatic -X"From tcsh:
setenv BETALINKOPTIONS="-L/usr/X11/lib -L$libXm_PATH -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -dc -dp -Bstatic -X"
~beta/configuration
folder by commenting out the
LD_LIBRARY_PATH
settings by typing a #
-sign
in front: env.sh
, line 171env.csh
, line 190Unknown flag: -woff
gcc
not supportedgcc
. 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 relocationthis 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:
beta -p
. This will preserve
the job-file, containing the link-directive(s) for the
program.
sgi
subdirectory, and has the same name as the application, but with
..job
appended.
-v
as argument to the last invocation
of
/bin/ld
in the job file.
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.
LD_LIBRARY_PATH
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.
There are 3 implications of this:
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.
LD_LIBRARY_PATH
specification: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.
demo/persistentstore/largeRead demo/persistentstore/crossloc
suspend
in a callback situation the program is
likely to crash.
demo/r4.0/tutorial/SquareRootwhich currently does not work on sgi. [corrected in r4.1]
Repetition subrange out of range Text parameter to C routine too big (max. 1000 bytes)
beta -o sgi/foo foo.betInstead you should do this:
beta -o foo foo.bet 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]
doGC
and scanobj
does not workdoGC
in betaenv
does not work
on SGI. This is used in implementation of
sysutils/v1.6/scanobjectsused in the demo
demo/sysutils/objinterface/scanobjwhich consequently does not work.
ld: WARNING 56: Invalid warning number (133)
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.
ld: WARNING 85: definition of vendorShellWidgetClass...
awenv
programs on SGI, the linker will
give the following warnings:
ld: WARNING 85: definition of vendorShellWidgetClass in /usr/lib/libXaw.so preempts that definition in /usr/lib/libXt.so. ld: WARNING 85: definition of vendorShellClassRec in /usr/lib/libXaw.so preempts that definition in /usr/lib/libXt.so.These warnings are caused by (intentional) overriding of the X Toolkit
VendorShell
in the SGI athena libraries.
The warnings can be safely ignored.