CLARIFICATION: Oberon System 3, Release 2.2 
Author Message
 CLARIFICATION: Oberon System 3, Release 2.2

In reaction to diverse recent comments on comp.lang.oberon I feel obliged
to clarify the situation with the language & compiler of our new release 2.2
of Oberon System 3.

(1.) The new release (exactly as all releases of System 3 before) supports
the full set of the original Oberon language without modification. This
language has proved powerful enough for all conceivable applications
and in particular for the implementation of Oberon System 3 itself.

(2.) However, new areas and new paradigms may require additional
expressiveness. This was certainly the case when we migrated from
functional reuse (as supported by Modula-2) to the reuse of data types
and structures (as supported by Oberon). Similarly, we need new
constructs, if we want to model "active" objects, i.e. objects with their
own local behavior (separate thread). We found that there is nothing
more natural than to upgrade record types and their scopes by constructs
already known in the language: Local procedures and body. It is important
to understand that local procedures in this context play a double role
(a) as type-wide methods and (b) as protected entries to the object
(providing mutual exclusion). In addition, object bodies suggest themselves
as a vehicule for the specification of an object's thread of control. Note
that the resulting programming model is highly unifying. Under a single
concept it comprises active objects, passive objects (record types w.o.
a body), "pure" records (data sets) and modules (single instance objects
of an anonymous type). Of course, no additional overhead (spacewise
or timewise) has to be paid for the special cases at run time.

(3.) An internal research project with active objects lead to an internal
(and pure) extension of Oberon tentatively called "Active Oberon".
Interestingly, the language "extensions" finally turned out to be removed
restrictions, and they contribute to both a more natural framework
for the specification of type-local functionality and to a simplification
of the (OP2-)compiler front-end, even in a single-process environment.
We decided not to artificially withhold these improvements from potential
software constructors. However, purists should simply ignore them.

(4.) For the convenience of users of Oberon-2 constructs, we have
further included an Oberon-2 compiler package in the release.

comp.lang.oberon readers who are interested in more details about
the rationale of "Active Oberon" should take a look at a paper that will
be presented in the upcoming Joint Modular Language Conference in
Linz, AU in March. It is located on:

"ftp://ftp.inf.ethz.ch/pub/Oberon/System3/Native/System/aopaper.ps"

I sincerely hope to have clarified with this message the current compiler
situation in connection with Oberon System 3, release 2.2. Of course,
I am always interested in discussing these and related issues on
a technical basis.

--Juerg Gutknecht



Tue, 17 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2

Hello!

I have read the Active Oberon paper - several times. As with most of
the work relating to Oberon, it is concise and fairly clear. It
proposes a simple extension to original Oberon which is both useful
and, in the author's own words, "unified, complete, and minimal".

However, there are some points of confusion, and I would like
to commment on these points, as well as the CLARIFICATION posting
which relates to it from comp.lang.oberon,

: In reaction to diverse recent comments on comp.lang.oberon I feel obliged
: to clarify the situation with the language & compiler of our new release 2.2
: of Oberon System 3.
:
: (1.) The new release (exactly as all releases of System 3 before) supports
: the full set of the original Oberon language without modification. This
: language has proved powerful enough for all conceivable applications
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: and in particular for the implementation of Oberon System 3 itself.

I am a bit confused by the wording of this statement. Why do you state
this so strongly when your intention is to propose a language extension?
My only guess is that Oberon suffers from a "minimalist stigmata" - that
is, to some, it seems to be too simple to be useful.

And yet, I could view this statement another way, I was under
the impression that Oberon-2 was the current "official" language, and
that any serious language evolution should start with Oberon-2 as
the base language, not Oberon(-1). I *could* interpret the above
statement as some sort of negative reflection on Oberon-2.

Perhaps I am just being defensive...

Could you please elaborate on why Active Oberon extends Oberon(-1)
and not Oberon-2?

: (2.) However, new areas and new paradigms may require additional
: expressiveness.

I can agree with this statement.

: This was certainly the case when we migrated from
: functional reuse (as supported by Modula-2) to the reuse of data types
: and structures (as supported by Oberon). Similarly, we need new
: constructs, if we want to model "active" objects, i.e. objects with their
: own local behavior (separate thread). We found that there is nothing
: more natural than to upgrade record types and their scopes by constructs
: already known in the language: Local procedures and body. It is important
: to understand that local procedures in this context play a double role
: (a) as type-wide methods and (b) as protected entries to the object
: (providing mutual exclusion).

The upgraded record types, which allow "optional procedure entries for
controlled access" ( or as you refer to them here "type-wide methods" ),
seem to sematically equivalent to the type-bound procedures of Oberon-2.

Could you please clarify as in what ways "procedure entries" are an
improvement over type-bound procedures?

: In addition, object bodies suggest themselves
: as a vehicule for the specification of an object's thread of control. Note
: that the resulting programming model is highly unifying. Under a single
: concept it comprises active objects, passive objects (record types w.o.
: a body), "pure" records (data sets) and modules (single instance objects
: of an anonymous type). Of course, no additional overhead (spacewise
: or timewise) has to be paid for the special cases at run time.

What are the limitations on record bodies? Initializers and record bodies
are *intended* to serve different purposes - initializers to set initial
values ( and I suppose, if necessary, to allocate local objects as well ),
and record bodies to describe the local thread of control. What is to
prevent a programmer from setting ( or re-setting ) initial values in a
record body? What is to prevent a programmer from providing "threaded"
behavior in an initializer?

If there are no such limitations, and if it is merely convention which
dictates the use of initializers and record bodies, then I see no reason
to have both. One or the other would be sufficient ( I'd guess the
initializer would be preferable - since it would be difficult to pass
parameters to a record body ). Can you please elaborate on why both are
necessary?

: (3.) An internal research project with active objects lead to an internal
: (and pure) extension of Oberon tentatively called "Active Oberon".
: Interestingly, the language "extensions" finally turned out to be removed
: restrictions, and they contribute to both a more natural framework
: for the specification of type-local functionality and to a simplification
: of the (OP2-)compiler front-end, even in a single-process environment.
: We decided not to artificially withhold these improvements from potential
: software constructors. However, purists should simply ignore them.

I am very confusing by this statement. Is AO a proposed language extension
or not? If so, why the statement "purists should simply ignore them"?

: (4.) For the convenience of users of Oberon-2 constructs, we have
: further included an Oberon-2 compiler package in the release.

I was almost insulted when I read this. It sounds as if you only provide
Oberon-2 because you have to. You seem to be ( if you allow me to
paraphrase (3) ) artificially withholding the improvements of Active
Oberon from Oberon-2 users.

Why must Oberon-2 and Active Oberon be incompatible?

---

Now, allow me to make a few observations and ask a few questions which
more directly deal with the Active Oberon paper. Unless otherwise noted,
quoted material is from the paper.

        "These concepts are integrated smoothly into the Oberon
         language by an upgrade of record types and the addition
         of one keyword and one built-in procedure."

I count SELF, EXCLUSIVE, SHARED, PASSIVATE(), PRIORITY(level), and
TIMESHARED. Also, procedure entries may have an option specification
clause ( optionlist ). This seems more than the addition of a keyword
and a built-in procedure. The changes are still minimal, but the above
statement seems to downplay exactly how much *has* changed.

SELF would be a redundant addition if type-bound procedure notation were
instead used.

EXCLUSIVE, SHARED, PRIORITY(level), and TIMESHARED are all to be used
within a procedure entry's option specification clause. The set-like
notation { } implies that more than one at a time may be present in
the optionlist. Which combinations are valid? Does the compiler flag
invalid combinations as errors? What other potential "runtime options
and directives" could there be? Once PRIORITY() is set, is the it fixed?
Or can the priority level be changed at runtime?

Passivate means ( from WWWebster Dictionary ):

        1 : to make inactive or less reactive <passivate the
        surface of steel by chemical treatment> 2 : to protect
        (as a solid-state device) against contamination by
        coating or surface treatment.

so that naming the procedure PASSIVATE() for guarded assertions seems to
make sense. Passivate is relatively obscure word ( though when looking at
it the first time, I guessed that it meant "to make passive" ). I would
have probably chosen something a little more common... AWAIT() perhaps.

        "Within the scope of a record type, (unqualified) names of
         its variables and procedures always refer to components of
         the current object."

If an object's procedure entry and a normal procedure located in the
same module both have the same name, how does one then access the normal
procedure? What if they have the same name but different parameter
lists, is there any special concern?

I'm not sure I understand the relationship between module types and
the upgraded record type. Are you simply saying that a module type
is a special ( anonymous ) case of record type? If so, then can we
now import modules locally within records? Can we import records
within other records?

I'm not sure how this view of module types

        "significantly increases the language's uniformity and
         "orthogonality", so that it appears to programmers and
         compiler-writers as a removed restriction much rather than
         as extension."

Could you please clarify this further?

Is there ever a case where either the call to the initializer or
execution of the record body is not performed ( assuming they are
both present )?

Looking at the declarations,

        Object = POINTER TO ObjDesc;
        ObjDesc = RECORD (ObjDesc0) (* derived from base-type ObjDesc0 *)
           VAR t: T;
               h: H;

           PROCEDURE P (t: T);
           BEGIN { EXCLUSIVE } ...
           END P;

           PROCEDURE& Init (t: T; h: H);
           BEGIN ...
           END Init;

        BEGIN ...
        END ObjDesc;

    VAR x: Object;
    BEGIN ... NEW (x, myT, myH); ... (* creation of pointer-based object *)
    END

    VAR X: ObjDesc(myT, myH); (* creation of static object *)

The differences in syntax between initialization of x and X seem
inconsistent to me. ( Is the object or the type being initialized? )
This notation could also invalidate the usual use of comma separated
lists in variable definitions for records,

        VAR X, Y: ObjDesc(myT, myH);   (* I'd guess an error here *)

        VAR X : ObjDesc(myT, myH); Y: ObjDesc(t, h);
        (* the corrected version *)

Maybe instead,

        NEW( x(myT, myH) );

and

        X(myT, myH): ObjDesc;

Actually, I'm not sure if that's all that much better. But it does seem
a little more consistent to me.

Also, what happens if we call NEW(x) or define X: ObjDesc; ? Are those
errors? Can you directly invoke Init at times after the object has been
instantiated?

Could you provide examples for preemptive priority scheduling? That is,
examples using the PRIORITY(level) and TIMESHARED options?

Consider the example,

    TYPE
        List = POINTER TO ListDesc;
        ListDesc = RECORD
           VAR buf, x: Item; line: INTEGER ;

           PROCEDURE Enter (x: Item);
           BEGIN { EXCLUSIVE } PASSIVATE (buf = nil ); buf := x
           END Enter;

           PROCEDURE Get ( var x: Item);
           BEGIN { EXCLUSIVE } PASSIVATE (buf # nil ); x := buf; buf := nil
           END Get;

           PROCEDURE& Init (listName: array of char );
           BEGIN buf
...

read more »



Sun, 22 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2



Quote:
>I have read the Active Oberon paper - several times. As with most of
>the work relating to Oberon, it is concise and fairly clear. It
>proposes a simple extension to original Oberon which is both useful
>and, in the author's own words, "unified, complete, and minimal".

>However, there are some points of confusion, and I would like
>to commment on these points, as well as the CLARIFICATION posting
>which relates to it from comp.lang.oberon,

I have also read the paper and I have a few tentative answers to some of your
questions. Keep in mind that this is in no way authoritative.

Quote:

>: In reaction to diverse recent comments on comp.lang.oberon I feel obliged
>: to clarify the situation with the language & compiler of our new release 2.2
>: of Oberon System 3.
>:
>: (1.) The new release (exactly as all releases of System 3 before) supports
>: the full set of the original Oberon language without modification. This
>: language has proved powerful enough for all conceivable applications
>                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>: and in particular for the implementation of Oberon System 3 itself.
[clip]
>Could you please elaborate on why Active Oberon extends Oberon(-1)
>and not Oberon-2?

Clearly the authors of the Active Oberon language prefer the traditional
class-based OOP style to the type-bound procedure style. I can't say that I
agree with them, but that's their perogative.

Quote:
>The upgraded record types, which allow "optional procedure entries for
>controlled access" ( or as you refer to them here "type-wide methods" ),
>seem to sematically equivalent to the type-bound procedures of Oberon-2.

>Could you please clarify as in what ways "procedure entries" are an
>improvement over type-bound procedures?

They do have this going for them: the AO style more closely matches nested
procs in programming style, and for this the direct reference to more global
variables makes sense. Specified recievers also look a little silly in nested
procedures so that explains their use of SELF.

On the other hand, nested procs can't be type-extended, so the metaphor breaks
down when you have to search to discover what field references to base types
mean. It is also quite easy to lose your place in large nested procs. These
are the main advantages to the TBP style, and why I prefer it.

Quote:
>: In addition, object bodies suggest themselves
>: as a vehicule for the specification of an object's thread of control. Note
>: that the resulting programming model is highly unifying. Under a single
>: concept it comprises active objects, passive objects (record types w.o.
>: a body), "pure" records (data sets) and modules (single instance objects
>: of an anonymous type). Of course, no additional overhead (spacewise
>: or timewise) has to be paid for the special cases at run time.

>What are the limitations on record bodies? Initializers and record bodies
>are *intended* to serve different purposes - initializers to set initial
>values ( and I suppose, if necessary, to allocate local objects as well ),
>and record bodies to describe the local thread of control. What is to
>prevent a programmer from setting ( or re-setting ) initial values in a
>record body? What is to prevent a programmer from providing "threaded"
>behavior in an initializer?

Nothing -- the initializer is done first though, operating in the parent
thread, and can take parameters

Quote:
>If there are no such limitations, and if it is merely convention which
>dictates the use of initializers and record bodies, then I see no reason
>to have both. One or the other would be sufficient ( I'd guess the
>initializer would be preferable - since it would be difficult to pass
>parameters to a record body ). Can you please elaborate on why both are
>necessary?

Most operating systems make it quite dificult to pass parameters directly to a
thread. Often they pass a pointer at most. It makes sense to split the
initialization and body in these cases. The initialization is performed in the
parent thread, the object is passed to the child thread, and the body is
performed there. Otherwise, there seem to be no restrictions on behavior.

Quote:
>: (4.) For the convenience of users of Oberon-2 constructs, we have
>: further included an Oberon-2 compiler package in the release.

>I was almost insulted when I read this. It sounds as if you only provide
>Oberon-2 because you have to. You seem to be ( if you allow me to
>paraphrase (3) ) artificially withholding the improvements of Active
>Oberon from Oberon-2 users.

>Why must Oberon-2 and Active Oberon be incompatible?

Given an implementation of AO, I could make an extension of O2 that does the
same thing in TBP style. That extension could be swapped in for the O2 parser
mentioned above. Simple. The trick would be getting the syntax as clean as AO
without the nested procs, but is as self-documenting as TPB style should be.

Quote:
>Now, allow me to make a few observations and ask a few questions which
>more directly deal with the Active Oberon paper. Unless otherwise noted,
>quoted material is from the paper.

>        "These concepts are integrated smoothly into the Oberon
>         language by an upgrade of record types and the addition
>         of one keyword and one built-in procedure."

>I count SELF, EXCLUSIVE, SHARED, PASSIVATE(), PRIORITY(level), and
>TIMESHARED. Also, procedure entries may have an option specification
>clause ( optionlist ). This seems more than the addition of a keyword
>and a built-in procedure. The changes are still minimal, but the above
>statement seems to downplay exactly how much *has* changed.

SELF is the keyword, PASSIVATE is the proc, and the rest are only predefined
in the options section.

[clip]

Quote:
>Passivate means ( from WWWebster Dictionary ):

>        1 : to make inactive or less reactive <passivate the
>        surface of steel by chemical treatment> 2 : to protect
>        (as a solid-state device) against contamination by
>        coating or surface treatment.

>so that naming the procedure PASSIVATE() for guarded assertions seems to
>make sense. Passivate is relatively obscure word ( though when looking at
>it the first time, I guessed that it meant "to make passive" ). I would
>have probably chosen something a little more common... AWAIT() perhaps.

On the other hand, it would fit in with ENTIER :).

Quote:
>        "Within the scope of a record type, (unqualified) names of
>         its variables and procedures always refer to components of
>         the current object."

>If an object's procedure entry and a normal procedure located in the
>same module both have the same name, how does one then access the normal
>procedure? What if they have the same name but different parameter
>lists, is there any special concern?

All major disadvantages that the TPB style fixes, so why not use it?

Quote:
>I'm not sure I understand the relationship between module types and
>the upgraded record type. Are you simply saying that a module type
>is a special ( anonymous ) case of record type? If so, then can we
>now import modules locally within records? Can we import records
>within other records?

A module is an instance, not a type, so you can't type-extend it. As for
importing, that is one of the many restrictions to record types that they
_didn't_ remove, along with CONST and TYPE sections.

Quote:
>I'm not sure how this view of module types

>        "significantly increases the language's uniformity and
>         "orthogonality", so that it appears to programmers and
>         compiler-writers as a removed restriction much rather than
>         as extension."

>Could you please clarify this further?

A record type changes from just a data structure (with TBPs) to a limited kind
of functor (a function that returns a typed module) that executes in parallel.
Modules become named record instances of anonymous type. This limited movement
towards functors does increase the orthogonality of the language, but not by
much, and not by as much as they imply.

All they really removed was the restriction that records have no block of code
that they execute, like modules did. This further similarity between modules
and records makes it easier for the compiler to use more of the same code to
implement both. This helps to simplify things quite a bit, which is a good
thing because the parallel processing makes things more complex.

All of the other syntax changes that they made (except for the active parts)
just make the code _appear_ to be more orthogonal. These changes (nested
methods, optional VAR in records, optional type name after END (and what does
that say when there isn't a type name?)) are just synatctic sugar that doesn't
simplify anything internally. Oh well.

Quote:
>Is there ever a case where either the call to the initializer or
>execution of the record body is not performed ( assuming they are
>both present )?

No.

Quote:
>Looking at the declarations,

>        Object = POINTER TO ObjDesc;
>        ObjDesc = RECORD (ObjDesc0) (* derived from base-type ObjDesc0 *)
>           VAR t: T;
>               h: H;

>           PROCEDURE P (t: T);
>           BEGIN { EXCLUSIVE } ...
>           END P;

>           PROCEDURE& Init (t: T; h: H);
>           BEGIN ...
>           END Init;

>        BEGIN ...
>        END ObjDesc;

>    VAR x: Object;
>    BEGIN ... NEW (x, myT, myH); ... (* creation of pointer-based object *)
>    END

>    VAR X: ObjDesc(myT, myH); (* creation of static object *)

>The differences in syntax between initialization of x and X seem
>inconsistent to me. ( Is the object or the type being initialized? )

The object is being initialized, not the type.

- Show quoted text -

Quote:
>This notation could also invalidate the usual use of comma separated
>lists in variable definitions for records,

>        VAR X, Y: ObjDesc(myT, myH);   (* I'd

...

read more »



Tue, 24 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2

Hello!

: >What is to
: >prevent a programmer from setting ( or re-setting ) initial values in a
: >record body? What is to prevent a programmer from providing "threaded"
: >behavior in an initializer?
:
: Nothing -- the initializer is done first though, operating in the parent
: thread, and can take parameters
:
: Most operating systems make it quite dificult to pass parameters
: directly to a
: thread. Often they pass a pointer at most. It makes sense to split the
: initialization and body in these cases. The initialization is performed
: in the
: parent thread, the object is passed to the child thread, and the body is
: performed there. Otherwise, there seem to be no restrictions on behavior.
:

I guess the next question would be is this split *conceptually* necessary
or is it an implementation detail? That is, does the programmer *need* to
know that initialization takes place in the parent thread, and the body
performed in the child? Or taken from another perspective, what if
this *isn't* the implementation used - does it still then make sense?

Because of the way initializers and record bodies are defined, your
explaination makes sense. But I don't see it as necessarily being so;
who owns the initializer? The parent? Or object being initialized?
Conceptually, if an object isn't active yet, how can it perform any
activities ( i.e. how can you call *any* of its procedures )?

Besides, in either static or dynamic allocations, the initializer does
*not* allocate the object itself. Initialization doesn't come until
after the object has been allocated.

You make a point that it is difficult to pass parameters directly to
a thread; but isn't that exactly what happens for any procedure
invocation of "type-wide methods"? Why should the initialzer be a
special case?

None of the examples in the AO paper show an option specification
clause for initialzers. Your response explains this; it doesn't need
it, the new thread hasn't started yet. If I give option specifications
in an initializer, is it a compile-time error?

: >        "These concepts are integrated smoothly into the Oberon
: >         language by an upgrade of record types and the addition
: >         of one keyword and one built-in procedure."
: >
: >I count SELF, EXCLUSIVE, SHARED, PASSIVATE(), PRIORITY(level), and
: >TIMESHARED. Also, procedure entries may have an option specification
: >clause ( optionlist ). This seems more than the addition of a keyword
: >and a built-in procedure. The changes are still minimal, but the above
: >statement seems to downplay exactly how much *has* changed.
:
: SELF is the keyword, PASSIVATE is the proc, and the rest are only
: predefined in the options section.

I'd say that EXCLUSIVE, SHARED, PRIORITY(level), and TIMESHARED
are at least pre-declared identifiers - putting them on the same
level as INTEGER, INC(), and TRUE ( *and* PASSIVATE() ).

The options section is a syntax change to procedure declarations.

It also seems to me that upgraded records, and especially initializers,
require more language rules than have been indicated.

I'm not saying these aren't valid additions in this context. But they
are all changes and shouldn't be discounted.

: >I'm not sure I understand the relationship between module types and
: >the upgraded record type. Are you simply saying that a module type
: >is a special ( anonymous ) case of record type? If so, then can we
: >now import modules locally within records? Can we import records
: >within other records?
:
: A module is an instance, not a type, so you can't type-extend it. As for
: importing, that is one of the many restrictions to record types that they
: _didn't_ remove, along with CONST and TYPE sections.

I'd be more impressed if this gave reflexive properties to modules
and allowed metaprogramming. Does this view of modules do that?

: All they really removed was the restriction that records have no block
: of code
: that they execute, like modules did. This further similarity between
: modules and records makes it easier for the compiler to use more of the
: same code to implement both. This helps to simplify things quite a bit,
: which is a good thing because the parallel processing makes things more
: complex.

This is great for compiler writers; but how does this view help me as a
programmer? Other than as "synatctic sugar"...

: >    BEGIN ... NEW (x, myT, myH); ... (* creation of pointer-based object *)
: >    END
: >
: >    VAR X: ObjDesc(myT, myH); (* creation of static object *)
:

I've thought about this some more. NEW(x, myT, myH) actually seems
pretty sensible. Though if you disallow NEW(x), then I would also say
a direct invocation of an intializer - say x.Init(myT, myH) -
should be an error.

It's the VAR X: ObjDesc(myT, myH) still bothers me. For one thing, it
makes things awkward because myT and myH have to be either globals or
parameters to the procedure which defines X.

But, if the initializer must always be called before the record body
executes, then VAR X: ObjDesc; doesn't make any sense. And then neither
does an explicit call to an initializer - or would the record body be
executed again as well?

Also consider,

   TYPE
        Record0 = RECORD
           VAR x, y: INTEGER;
           ...
           (* PROCEDURE& Init (x, y: INTEGER); Oops... x and y would hide
                                               record fields.  *)
           PROCEDURE& Init (x1, y1: INTEGER);  (* Use different names *)
           BEGIN x := x1; y := y1
           END Init;

        BEGIN
           ...
        END Record0;

        Aggregate = RECORD
           VAR r: Record0(x, y); (* I *have* to initialize it here? *)
           ...
           PROCEDURE& Init ( x, y: INTEGER );
           BEGIN (* ??? How would I pass x and y to r's initializer? *)
           END Init;
        BEGIN
           ... (* There's no way to pass x and y to r's initilizer from
                  here either *)
        END Aggregate;

: >That's another thing - what about all those other potential extensions
: >to Oberon? Operator overloading, "parametric polymorphism", and so forth
: >- how do those ideas fit in with Active Oberon? If the language is
: >ready for its next iteration, should we not consider these other things
: >as well?
:
: As I recall, none of those extensions were proposed by Patrik Reali.
: AO is his
: baby after all.

That's not the point. The impression that many of us are getting is that
AO is to be the next "official" version of Oberon. If AO were an
experimental language, fine - none of us would object.

But we as users of Oberon don't want to sit quietly by while changes
come from on high. If there is to be a major revision to the language,
we'd like to have a say ( or at least feel like the "masters" are
listening to our concerns ) as to what will be changed.

: But as for those extensions:
: Operator overloading: Looking at code written with overloaded operators,
: it is
: difficult to determine what that code is actually doing. Oh, it's somewhat
: easy to determine what the programmer hopes it will do (they do look
: pretty, don't they? ;-) but who knows what module the operator was defined
: in, or what
: it really does. Does it have side effects? Will it trap? You are used to
: asking these questions with functions (except in Oberon-V) but you can at
: least tell immediately where a function is defined. I wouldn't recommend
: them.

I'm not a big fan of operator overloading... but that doesn't mean I
won't listen to sensible proposals about it. R. Morelli's diploma
thesis concerns overloading ( among other things ), and I look forward
to reading it when it becomes available.

: Parametric polymorphism: This is what you get when you replace the Oberon
: style of doing modules with the ML style, functors and all. At least that
: would be the effect if you added this to AO. Do we really want to do this?

I'm not sure I understand your objection. Could you provide an example?

Roe and Szyperski's paper on parametric polymorphism for Oberon had its
own share of contensious points. If I thought it were at a point
where this feature was going to be added to Oberon, I'd have as much
to say about it as I did about AO.

--
Eric
---
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   _Common Sense_ does not mean that good sense which is common, or commonly
   needed in the ordinary affairs of life, but the sense which is common to
   all the five, or the point where the five senses  meet, supposed to be
   the seat of the soul, where it judges what is presented by the senses,
   and decides the mode of action.
        -- The Dictionary of Phrase and Fable
        -- http://www.bibliomania.com/Reference/PhraseAndFable/

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Sat, 28 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2

Quote:

> As I recall, none of those extensions were proposed by Patrik Reali. AO is his
> baby after all.

Just a clarification: AO is not my baby, AO is a team effort,

leaded by Prof. J. Gutknecht.

My own contribution is the implementation of the AO-Compiler.

Patrik

--

Patrik Reali, Institute for Computer Systems, ETH Zurich

phone:  ++41 1 632 73 23


www:    "http://www-cs.inf.ethz.ch/~reali"



Mon, 30 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2


Quote:
>Hello!

I think that I see what is confusing you. You are running into a
problem with your terminology. Let me see if I can explain it
before I answer some of your questions.

Traditional OOP (non-active) generally has only classes (object
types, in OOP's that support them) and objects (or object instances
in class-based OOP). All objects are passive in this kind of OOP,
or would be considered so if programming in an active OOP style.
Often these objects (or classes) have operations bound to them,
but they don't actually do anything themselves. This is a
distinction that many of the proponents of the traditional OOP
style don't understand or choose to ignore. The terms that they
use imply that the operations that are bound to the object are
performed by the object itself, perhaps with prompting from the
outside, such as calling type-bound procedure calling "message
passing". Most of the time this implication is misleading; often
it is completely wrong. An apple does not eat itself.

An active object (or "subject", to continue the grammar terms) has
a thread of control in addition to its bundled operations. The
active object can apply its operations to itself in the course of
performing its action, but can also do other things, perhaps to
other objects. At the same time (perhaps conceptually) it can be
manipulated from the outside by other objects also applying its
operations to it. Thus an active object can be the object and the
subject of different sentences at the same time, so to speak.

If I seem to be too vague, it is because there are probably more
OOP methodologies than you think. Some have active objects, some
don't, some functional OOP paradigms don't even have any form of
action in the procedural sense. Only a minority have classes; some
only have unique objects, others have factories. It can get quite
confusing if you try to apply terms out of context.

That given, let's get to some specifics.

Quote:

>: >What is to prevent a programmer from setting ( or re-setting )
>: >initial values in a record body? What is to prevent a programmer
>: >from providing "threaded" behavior in an initializer?
>:
>: Nothing -- the initializer is done first though, operating in the
>: parent thread, and can take parameters
>:
>: Most operating systems make it quite difficult to pass parameters
>: directly to a thread. Often they pass a pointer at most. It makes
>: sense to split the initialization and body in these cases. The
>: initialization is performed in the parent thread, the object is
>: passed to the child thread, and the body is performed there.
>: Otherwise, there seem to be no restrictions on behavior.

>I guess the next question would be is this split *conceptually*
>necessary or is it an implementation detail? That is, does the
>programmer *need* to know that initialization takes place in the
>parent thread, and the body performed in the child? Or taken from
>another perspective, what if this *isn't* the implementation used -
>does it still then make sense?

It makes sense because there may be times when you only want the
child to be passive and so don't provide a body; in those cases you
won't have a child thread, with all of its startup overhead. It also
allows you to pass VAR parameters to the init without worrying about
the values getting changed while you're using them. It also makes it
so that NEW is synchronous rather than asynchronous.

Quote:
>Because of the way initializers and record bodies are defined, your
>explaination makes sense. But I don't see it as necessarily being so;
>who owns the initializer? The parent? Or object being initialized?

Neither. The object type owns the initializer. The init is just another
method that is flagged to be called by the NEW proc, but can also be
called at other times, even by the object itself.

Quote:
>Conceptually, if an object isn't active yet, how can it perform any
>activities ( i.e. how can you call *any* of its procedures )?

When it calls its procedures itself, or other procedures, it is active.
When you call its procedures, you are acting upon it.

Quote:
>Besides, in either static or dynamic allocations, the initializer does
>*not* allocate the object itself. Initialization doesn't come until
>after the object has been allocated.

Right.

Quote:
>You make a point that it is difficult to pass parameters directly to
>a thread; but isn't that exactly what happens for any procedure
>invocation of "type-wide methods"? Why should the initialzer be a
>special case?

That is not what happens. Although AO doesn't encourage you to make a
distinction between the object and the object's activity, you must do
so in order to understand how it works. When the object's action (its
body) does something, it is performed by the object's thread. In fact
that it has one action for each of its inherited bodies, all performed
concurrently (a wierd, AO-specific idea). One of the things that an
object's action can do is manipulate the object's data; another is to
call some of its methods. It can also manipulate other objects' data
or call their methods or spawn new objects -- these are all operations
that act upon other objects, but are not activities _of_ other objects.
The initializer doesn't pass parameters to a thread; NEW does that, in
the form of the hidden SELF parameter, in the course of spawning the
object's bodies, _after_ applying the method flagged as initialization
to the object's data. The initializer is otherwise a normal method.

Quote:
>None of the examples in the AO paper show an option specification
>clause for initialzers. Your response explains this; it doesn't need
>it, the new thread hasn't started yet. If I give option specifications
>in an initializer, is it a compile-time error?

No.

Admittedly, they make no difference when the init is initially called
by NEW since at that point the init is naturally EXCLUSIVE (how could
it be otherwise?). They would matter when you called the method again.
Remember that the init flag only applies to the init behavior; the
method flagged is otherwise normal and can be called millions of times.

- Show quoted text -

Quote:
>: >        "These concepts are integrated smoothly into the Oberon
>: >         language by an upgrade of record types and the addition
>: >         of one keyword and one built-in procedure."
>: >
>: >I count SELF, EXCLUSIVE, SHARED, PASSIVATE(), PRIORITY(level), and
>: >TIMESHARED. Also, procedure entries may have an option specification
>: >clause ( optionlist ). This seems more than the addition of a keyword
>: >and a built-in procedure. The changes are still minimal, but the above
>: >statement seems to downplay exactly how much *has* changed.
>:
>: SELF is the keyword, PASSIVATE is the proc, and the rest are only
>: predefined in the options section.

>I'd say that EXCLUSIVE, SHARED, PRIORITY(level), and TIMESHARED
>are at least pre-declared identifiers - putting them on the same
>level as INTEGER, INC(), and TRUE ( *and* PASSIVATE() ).

They are only declared in the options section. Elsewhere they have no
predefined meaning. Similarly, even if you declare them as identifiers
you don't change their meaning in the options section, nor can you
declare new options.

Quote:
>The options section is a syntax change to procedure declarations.

>It also seems to me that upgraded records, and especially initializers,
>require more language rules than have been indicated.

>I'm not saying these aren't valid additions in this context. But they
>are all changes and shouldn't be discounted.

Right.

Quote:
>: >I'm not sure I understand the relationship between module types and
>: >the upgraded record type. Are you simply saying that a module type
>: >is a special ( anonymous ) case of record type? If so, then can we
>: >now import modules locally within records? Can we import records
>: >within other records?
>:
>: A module is an instance, not a type, so you can't type-extend it. As for
>: importing, that is one of the many restrictions to record types that they
>: _didn't_ remove, along with CONST and TYPE sections.

>I'd be more impressed if this gave reflexive properties to modules
>and allowed metaprogramming. Does this view of modules do that?

Oberon System 3 2.2 already has some limited metaprogramming that applies
to modules and records. There is nothing about AO that would affect that.

Quote:
>: All they really removed was the restriction that records have no block
>: of code that they execute, like modules did. This further similarity
>: between modules and records makes it easier for the compiler to use more
>: of the same code to implement both. This helps to simplify things quite
>: a bit, which is a good thing because the parallel processing makes things
>: more complex.

>This is great for compiler writers; but how does this view help me as a
>programmer? Other than as "synatctic sugar"...

No way that I can think of, unless you're programming the compiler ;-)

Quote:
>: >    BEGIN ... NEW (x, myT, myH); ... (* creation of pointer-based object
*)
>: >    END
>: >
>: >    VAR X: ObjDesc(myT, myH); (* creation of static object *)
>:

>I've thought about this some more. NEW(x, myT, myH) actually seems
>pretty sensible. Though if you disallow NEW(x), then I would also say
>a direct invocation of an intializer - say x.Init(myT, myH) -
>should be an error.

Before the pointer is initialized, it is NIL; you can't call methods of
a NIL pointer. After the pointer is initialized, Init is just another
method, no longer special. The main advantage of the flagged init is
that it _will_ be called, count on it.

- Show quoted text -

Quote:
>It's the VAR X: ObjDesc(myT, myH) still bothers me. For one thing, it
>makes things awkward because myT and myH have to be either globals or
>parameters to the procedure which defines X.

>But, if the initializer must always be called before the record body
>executes, then VAR X: ObjDesc; doesn't

...

read more »



Tue, 31 Aug 1999 03:00:00 GMT  
 CLARIFICATION: Oberon System 3, Release 2.2

Quote:


>> As I recall, none of those extensions were proposed by Patrik Reali.
>>AO is his baby after all.

>Just a clarification: AO is not my baby, AO is a team effort,
>leaded by Prof. J. Gutknecht.

>My own contribution is the implementation of the AO-Compiler.

I stand corrected.

I can't recall any of the other members of the team proposing operator
overloading or parametric polymorphism either, at least on usenet. I am
quite prepared to be wrong about this too :-) .

Quote:
>Patrik

Brian


Thu, 02 Sep 1999 03:00:00 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. NEW RELEASE: Oberon System 3, Release 2.2

2. NEW RELEASE: Oberon System 3, Release 2.2

3. Linux Oberon System 3 Release 2.2 for X Windows

4. New release of Linz Oberon V4 Release 2.2

5. 'abck' 2.2 Intrusion Reporting System Released

6. RELEASED Python 2.2 release candidate 1 is out!

7. RELEASED Python 2.2 release candidate 1 is out!

8. Translation: Neues Motherboard für Oberon V3 2.2

9. Neues Motherboard für Oberon V3 2.2

10. Anwender Prog. für Oberon V3 2.2

11. HP500 Problem - Bug in PC Native Oberon 2.2 ?

12. SPARC-Oberon 2.2

 

 
Powered by phpBB® Forum Software