[Oberon] (no subject)

Patrik Reali reali at acm.org
Sat Aug 24 00:57:54 CEST 2002


From: "Frank van Riet" <Fvanriet at spescom.com>
> 1) The lack of unsigned data types is a great annoyance. Sure there are
ways
> of getting around this, but
> I cannot see that Oberon has gained anything as a language by not
> supporting unsigned types. Sure
> it makes the compiler simpler, but not significantly. Perhaps it is
> because of the potential complexities
> of mixing signed and unsigned types in expressions ?  This also does
> not seem like a convincing argument.
> It could simple have been disallowed.
>

In fact I remember discussions going in the other direction: having only one
generic integer type. This follows the observation that you basically need
to specify the type size only when dealing with memory (e.g. accessing
hardware registers or to save space on a large array). (Don't worry, we're
not changing anything). Java uses a similar approach, where all computations
are performed using the machine word size, and smaller types are only use to
store/load data.

The only cases where I had to deal with unsigned is when building low level
code, but then values are used to represent bit-patterns, and thus the SET
type is more appropriate. This can cause some painful experiences when
porting C code that doesn't make the distinction, but in fact it is an
advantage: either you use a value as a flag or as a number, mixing is not
good (by enforcing this design I was even able to find a few bugs in a linux
driver).

As you can deduce, I'm not very convinced that unsigned integers are badly
needed (and not only because of the huge amount of work required to have
them, which would have a negative impact on the compiler). As a side note,
using SYSTEM.VAL has no perfomance impact, as it only affects the way the
compiler interprets a variable.


> 2) In developing large systems for different platforms, conditional
> definintions are a real life saver.
> (e.g. (Borland?) Pascal's $IFDEF) I'm not sure if this is a language
> or an implementational issue, although I suspect it is the former. Apart
> from having code for differing platforms. Conditionals will
> get rid of the clutter of debugging code
>
> CONST
> debug = TRUE;
> ;;;
> IF debug THEN ....
>
> which is painfully inefficient.
>

Why is this inefficient? OP2 (and Paco) perform constant folding and
dead-code elimination, thus this code is not evaluated nor generated at all.
The only problem is when using different types.

Anyway, conditional compilation is not a language issue, but more the case
for a filter to be used before the compiler gets the source.

In Oberon and Bluebottle the problem was solved by making a distinction
between modules that are portable, have a portable interface, or are not
portable at all. Machine dependent code is isolated in one or more modules
that are simply swapped at compilation time, e.g.:

Compiler.Compile \.Obx
    MachineA.Core.Mod Common.Mod ~
Compiler.Compile \.Oby
    MachineB.Core.Mod Common.Mod ~

this compiles a set of modules for machine A using the suffix Obx and for
machine B using the suffix Oby.

(as an exercise, you can go through the modules in the bluebottle release
and discover which ones use this pattern). This way we where able to create
many systems that share some common modules (the whole native oberon family
and bluebottle running on two different platforms).

In fact, we had a simple preprocessor to handle conditional code built in
the Builder module, but we decided not to use it because it made the code
much more complicated and more difficult to understand and manage. I used it
to cope with the different calling conventions used in the windows, linux,
and oberon back-ends of the intel compiler, but it made the code ugly. At
the end, we added the three versions to the back-end and used a variable to
switch between them, which allowed to have only one compiler that fitted all
intel systems, and to dynamically change the calling convention per
procedure (this was done by Emil, and allowed to interoperate with libraries
using the C calling convention).


> 3) Dynamic array headers: Why was the decision made to to stick the header
> in the middle of the structure
> and not in-front as with other structures. Not only is it
> non-intuitive nit having the pointer point
> to the firts element, but it would also make language
> interoperability very difficult. Let alone the
> nightmare of porting older code in which this was not the case...
>

This is the price for using a garbage collector.

I don't understand your point on language interoperability. I see two
possible cases:
* you interoperate with a language without GC (guess C/C++). In this case
the only safe approach is either using a JNI-like approach (you call system
procedures that do the convertion for you) or like in Plugin Oberon for
Windows, where it is possible to specify the data-layout and
calling-convention (e.g. an open array parameter could be tagged to make the
compiler pass a pointer to the data instead of the descriptor; you must be
extra careful with the GC and hope that your C-client doesn't mess with
memory.

* using langauge that supports garbage-collection (I would guess Java and
C#), you get the code in an intermediate representation that you must either
interpret or compile, so that you get to choose the data-layout (and will
hopefully choose one compatible to Oberon) and have no such problem. This is
what is done in Jaos (Java VM for bluebottle).


> 4) Pragmas are only allowed on a per module basis. It would be very
usefull
> to disable type guard checking
> in many cases, simply for the sake of efficiency. True it
> compromises security, but why allow it
> at all then.

This makes sense. I will consider it for both compilers (though with low
priority).

>
>
> As an aside does anyone know whether read-only exports are still supported
?
>

They are available in OP2 when you compiler with \2 (parse Oberon-2)


-Patrik




More information about the Oberon mailing list