[comp.lang.modula2] Nested routines as values?

ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (01/19/91)

I heard a rumour from a colleague that the Modula-2 standards people were
considering allowing routines declared within other routines to be
passed as values of PROCEDURE types. Can anybody tell me if this is true?

I think it's a good idea, unless it means that PROCEDURE values become
descriptors, instead of straight addresses. If that's the case, it's
going to make it very cumbersome to interface to non-Modula-2 code.

Lawrence D'Oliveiro                       fone: +64-71-562-889
Computer Services Dept                     fax: +64-71-384-066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00

news@m2xenix.psg.com (Randy Bush) (01/20/91)

ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:

> I heard a rumour from a colleague that the Modula-2 standards people were
> considering allowing routines declared within other routines to be
> passed as values of PROCEDURE types. Can anybody tell me if this is true?

While it was considered, I believe that embellishment was forgone.

> I think it's a good idea, unless it means that PROCEDURE values become
> descriptors, instead of straight addresses. If that's the case, it's
> going to make it very cumbersome to interface to non-Modula-2 code.

And you even know why <grin>.

So, unless you are willing to forgo access to intermediate lexic scopes or have
proc vars be more than addresses ...
-- 
..!{uunet,qiclab,intelhf,bucket}!m2xenix!news

brandis@inf.ethz.ch (Marc Brandis) (01/21/91)

In article <1991Jan19.151918.2734@waikato.ac.nz> ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>I heard a rumour from a colleague that the Modula-2 standards people were
>considering allowing routines declared within other routines to be
>passed as values of PROCEDURE types. Can anybody tell me if this is true?
>
>I think it's a good idea, unless it means that PROCEDURE values become
>descriptors, instead of straight addresses. If that's the case, it's
>going to make it very cumbersome to interface to non-Modula-2 code.
>

As far as I know, there are only two ways to implement it. One is to assign 
a scope pointer together with the procedure address, which would mean making
the procedure type a descriptor. The scope pointer would be the static link
of the enclosing procedure. 

The other way is referred to in our institute as "global display". It is
nothing but a global array with a field for each procedure including other
procedures, in which the static link can be stored. References to outer scopes
go through this global display. We had this implement in an experimental
Oberon compiler, and as far as I know we were the first to do this.

The first method has the disadvantage that procedure variables become larger
and that they are no more compatible with other languages. Another 
disadvantage is that the scope pointer in the descriptor could possibly be
used to access a stack frame that does no more exist. This could only be
avoided when the language makes sure that the pointer is destroyed when the
enclosing procedure terminates. One way to do this is not to allow the 
procedure to be assigned to a variable but only to be passed as a parameter.
However, this would mean introducing a new type with very special rules just
for this purpose. 

The second method has the advantage that the scope pointer used by all others
can be reset at the end of the procedure. However, how well this construct
would interface to other languages is an open question (I guess badly). 
Moreover, it does not work in the context of multitasking, as the global
display would have to be shared among different tasks. Introducing a global
display for each task would solve this problem, at the cost of another level
of indirection and more complicated task management. But the biggest problem
is that the construct has a very special semantics when recursion is used:
The scope accessed is always the one at the topmost level, even if the 
procedure has been passed at a lower level. This can cause problems that are
extremly hard to find. 

As a whole, I do not think that this is a really good idea. The only advantage
of having the possibility to pass local procedures as procedure variables is
to write generic broadcast procedures for data structures without having to
use global variables. The variables of the enclosing procedure could be used
instead. However, as exactly this feature has an unclear semantics and can
improve performance only by a little bit (even depending on the machine
architecture), I would say the best thing would to drop the idea as soon as
possible.


Marc-Michael Brandis
Computer Systems Laboratory, ETH-Zentrum (Swiss Federal Institute of Technology)
CH-8092 Zurich, Switzerland
email: brandis@inf.ethz.ch

ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (01/24/91)

Thanks to those people who correctly pointed out that a nested routine
needs some way to access local variables at the outer level, and who
mentioned the two well-known mechanisms for doing so. However, this
makes no difference to my point: there is still no need to pass such
a routine (as a value of a PROCEDURE type) in the form of a descriptor,
to allow such accesses to take place. You can do it with just an
address.

Certainly the onus is on the programmer to ensure that no references
to such an object remain around when the enclosing routine terminates.
The same thing applies to using the ADR function on a local variable,
and as I recall, Modula-2 includes no special types to enforce the
restriction in this case!

Lawrence D'Oliveiro                       fone: +64-71-562-889
Computer Services Dept                     fax: +64-71-384-066
University of Waikato            electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00