
Oberon-2 *restriction* proposal
I wrote about the non-local effects of WITH statements:
Quote:
>> PROCEDURE p (VAR v: T0);
>> VAR w: T0;
>> BEGIN
>> WITH v: T DO p(w) ... END
>> ...
>> This procedure will not compile, as the parameter 'v' of 'p' looks as if it
>> had been declared as 'T' inside the WITH statement, so p(w) will not compile
>> as 'w' is not assignment compatible to 'v:T'.
>Do you mean it seriously that a WITH statement on a formal argument (v)
>affects the signature of the procedure (p) ?
Yes. The formal argument is part of the signature, so making v 'look as if it
had been declared as T' also affects the signature. I am not saying that this
is the only possible semantics of it, but this is the way it is now.
Quote:
> [explanations of the insecurity of the WITH statement deleted]
>> Considering that the desired and safe effects of the WITH statement can be
>> achieved using (i) and (ii), I would rather vote for dropping (iii) and
>> leaving the other two in the language. The main objective against dropping
>> the WITH statement is performance, as it has to be replaced by guarding the
>> designator on each occurence. A simple compiler may not be able to remove
>> redundant guards, making some kinds of code considerably slower.
>Well, are we speaking of the WITH statement as a notational convenience
>(which then might make other notations obsolete because it covers the
>most frequent cases, IMHO), or as a construct with its own
>--possibly insecure-- semantics?
The WITH statement is not just a notational convenience. Note that other such
'notational conveniences' were dropped when Oberon was developed, for example
the unqualified import. I believe the most important reason for its
introduction was efficiency.
In my opinion, there are enough cases where having just the WITH statement
would be a major inconvenience. Let me give you an additional example, where
it really is a pain.
TYPE
Node = POINTER TO NodeDesc;
NodeDesc = RECORD
END;
ListNode = POINTER TO ListNodeDesc;
ListNodeDesc = RECORD (NodeDesc)
x: INTEGER;
next: Node
END;
VAR
p: Node;
BEGIN
p := root;
WHILE (p # NIL) & (p(ListNode).x # key) DO
p := p(ListNode).next
END
Writing this using the WITH statement would get you more complex code which is
harder to read in my opinion.
VAR
found: BOOLEAN; p, q: Node;
BEGIN
p := root; found := FALSE;
WHILE (p # NIL) & ~found DO
WITH p: ListNode DO found := p.x # key; q := p.next END;
IF ~found THEN p := q END
END
Quote:
>A regional guard could very well be understood as a purely notational
>facility which does not impair security (nor immediately implies
>greater efficiency).
How would that be defined? Would it also apply to complex designators, e.g.
could I write
WITH p.next : ListNode DO ... END
? For a notational convenience, this looks reasonable to me. But there are
more complex cases, e.g.
WITH p.a[i+1] : ListNode DO ... END
Which designators would that guard apply to? Would it mean that every
occurence of 'p.a[i+1]' (lexically) would be guarded, or would 'p.a[i]' also
be guarded?
Quote:
>Section 9.11 in "The Programming Language Oberon-2" is self-
>contradictory in this respect: First, it states that WITH statements
> "... apply a type guard to every occurrence of the tested variable
> within this statement sequence";
>later on, it speaks of the guarded variable
> "... where v is regarded as if it had the static type T1",
>which suggests that there is only one type test at the entry of the
>WITH statement but no further type tests in its body.
Agreed. This is why I used the definition in the original Oberon report. The
idea is that there is only a single type test at the entry of the WITH
statement.
Marc-Michael Brandis
Institute for Computer Systems
ETH-Zentrum (Swiss Federal Institute of Technology)
CH-8092 Zurich, Switzerland