[Oberon] Procedure variables and local procedures
skulski at pas.rochester.edu
Fri Sep 29 16:04:53 CEST 2017
thank you! I should have known that NW predicted my question and answered it ahead of being asked.
From: Oberon [oberon-bounces at lists.inf.ethz.ch] on behalf of Andreas Pirklbauer [andreas_pirklbauer at yahoo.com]
Sent: Friday, September 29, 2017 9:22 AM
To: ETH Oberon and related systems
Subject: [Oberon] Procedure variables and local procedures
> From: Skulski, Wojciech skulski at pas.rochester.edu<mailto:skulski at pas.rochester.edu> Fri Sep 29 14:34:06 CEST 2017
> What happens when the enclosing procedure GlobalProc declares its local variables, which are then used within its local procedure? > Local variables are allocated on the stack. Does the "counter" exist when the procedure IncCounter is called by a client module?
> MODULE M;
> TYPE Proc* = PROCEDURE;
> VAR GlobalProc*: Proc; (*exported*)
> LocalProc: Proc; (*not exported*)
> PROCEDURE GlobalProc2;
> VAR LocalVar2: Proc;
> counter: INTEGER; (*allocated on the stack*)
> PROCEDURE ZeroCounter; BEGIN counter := 0 END ZeroCounter;
> PROCEDURE IncCounter; BEGIN counter := counter + 1 END IncCounter;
> BEGIN (*GlobalProc2*)
> GlobalProc := IncCounter; (*allowed (LocalProc2 visible in current scope)*)
> LocalProc := ZeroCounter; (*allowed (LocalProc2 visible in current scope)*)
> END GlobalProc2;
> BEGIN (*M*)
> GlobalProc2(); (*assign the variables*)
> ZeroCounter (); (*calling proc local to the module via proc variable*)
> (*IncCounter can now be called by clients. Can it be really?*)
> END M.
your (modified) module M will not compile when compiled with an Oberon-07 compiler, but return a “level error, not accessible” error message. The reason is that access to intermediate variables is no longer allowed in Oberon-07 (it was in the original version of the Oberon language published in 1988, but it no longer is).
This means that a local procedure (as your procedure ZeroCounter) can only modify *strictly* local variables (i.e. declared local to ZeroCounter) or *strictly* global variables (i.e. declared as global variables in module M), but nothing in between. Therefore, modifying the variable “counter” (which is declared local to GlobalProc2, i.e. at an intermediate level) from within the local procedure ZeroCounter is not permitted in Oberon-07. Hence the error message. And this is precisely the one change in the language that was necessary to make my original version of module M work.
It’s that the language itself has changed with Oberon-07 around 2007, and for good reasons. For some additional insight into this decision, see ch. 12.2. on p.73 of https://www.inf.ethz.ch/personal/wirth/CompilerConstruction/CompilerConstruction2.pdf<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.inf.ethz.ch_personal_wirth_CompilerConstruction_CompilerConstruction2.pdf&d=DwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-ybV0&m=owIZbwd1g6gK1lNv4-oJtunzLfOEb7n4gPqjS2-v3SU&s=Xno4b7RTo3YlgR2zkruZUyKVK1LvuLg0rU8eFmmzFzE&e=> ("In fact, programming experience has shown that the access of intermediate level variables is bad practice and better be avoided. Implementers must welcome this insight, as it makes the static link superfluous.”)
More information about the Oberon