![]() |
| Home > Programming > |
FAQ: BETA Programming Language (version 1.11 - 08 Dec 97) |
Section 3 of 6 - Prev - Next
All sections - 1 - 2 - 3 - 4 - 5 - 6
(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 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
and
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.
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+]
----------------------------------------------------------------------------
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:
=
= (|"_")+(||"_")*
= "'"*"'"
where can be any char except "'" and newline.
"'" are allowed in , iff preceeded with "\".
"\n", "\t", etc. are allowed in to
represent non-printable chars - see Compiler
manual (mia91-02) for details.
= (||) where
= +
= ("X"|"x")
= (|)+
= ["."][("E"|"e")[("+"|"-")]]
= "a"|"b"|...|"z"|"A"|"B"|...|"Z"
= "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 Mjolner System?
The Mjolner 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: "Mjolner System" was formerly designated "Mjolner BETA system".)
----------------------------------------------------------------------------
E02) What does the Mjolner System contain?
The Mjolner 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 Mjolner System are constructed
using the BETA language.
Major parts of the Mjolner 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 Mjolner 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 p12 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 p18 for more details.
Container libraries
The standard container data structures are organized in the following
inheritance hierarchy of patterns:
container
_________________|__________________________
| | | |
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 in BETA 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 Manual for more details.
----------------------------------------------------------------------------
E04) What frameworks come with the Mjolner 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 Mjolner System contains from release 4.0 a platform independent
framework for the construction of graphical user interfaces, called
guienv..
X Window System framework
The Mjolner 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 Mjolner 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 Mjolner 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 Mjolner 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 Mjolner 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 Mjolner BETA CASE Tool provides
o graphical structure editing of design diagrams
o textual structure editing of programs
o automatic program generation from design diagrams
o reverse engineering from programs to design diagrams
o simultaneous editing of design diagrams and programs
No CASE gap:
o A single abstract language is used throughout analysis, design,
and implementation.
o Different concrete syntaxes are used to present the different
models:
+ graphical syntax for design
+ textual syntax for programs
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 Mjolner System.
This beta-mode is in the public domain and can be obtained by FTP at
ftp://ftp.daimi.aau.dk/pub/beta/emacs.
----------------------------------------------------------------------------
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
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[]
<>
#)
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).
----------------------------------------------------------------------------
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:
fSource.bet:
ORIGIN '...';
BODY 'fBody'
--- lib: attributes ---
f: (# t: @text;
<>
enter t[]
<>
#)
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: @<>
enter t[]
<>
#)
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.
----------------------------------------------------------------------------
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.
fSource.bet:
ORIGIN '...'
--- lib: attributes ---
f: (# t: @text;
<>
enter t[]
<>
#)
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 Mjolner 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:
fSource.bet:
ORIGIN '...'
--- lib: attributes ---
A: (# V:< T;
...
#);
B: A(# <>
...
#);
C: B(# V::< T1;
...
#)
fUsage.bet:
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 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.
----------------------------------------------------------------------------
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:
top.bet:
ORIGIN '~beta/basiclib/v1.6/betaenv';
BODY 'testBody'
--- lib: attributes ---
test: (# do <> #)
--- 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.
----------------------------------------------------------------------------
F08) Can <> be used instead of <>?
The fragment system has a pragmatic treatment of the syntactic categories
<> and <>. In general one may want to leave slots
in a delaration list for inserting declarations as in:
(# a: @integer;
<>;
b: ^ text;
<>;
c: (# ... #)
#)
It is, however, not possible to generate the above form from the BETA
grammar, since the nonterminal 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;
<>;
b: ^ text;
<>;
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 to be inserted for an . This aliasing
between and 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 as a shorthand for . 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/current/awenv'
--- program: descriptor ---
AwEnv
(# Hello: @Label;
do Hello.init;
#)
whereas the following program creates a window containing "Hello"
ORIGIN '~beta/Xt/current/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
Section 3 of 6 - Prev - Next
All sections - 1 - 2 - 3 - 4 - 5 - 6
| Back to category Programming - Use Smart Search |
| Home - Smart Search - About the project - Feedback |
© allanswers.org | Terms of use