[Oberon] Oberon for a C++ user.

Skulski, Wojciech skulski at pas.rochester.edu
Mon Oct 3 09:07:41 CEST 2016


Andreas:

the problem IMHO is in the operator :=, which is overloaded. The procedure variables are not a variables in the usual sense. The operator := should not apply to them.

A regular variable has a value. The value is passive. It gets acted upon by a client. The variable is not doing anything on its own. Somebody is doing something with the variable (somebody is using its value for some goal).

IF var1 = var2 THEN... (*passive role of the variables*)

The procedure variable has a value (the address to jump to), and also a behavior. The value is passive, but the behavior is active. The value is retained after unloading the implementation, but the behavior is damaged. This is the problem. 

The value (the address) is not that important. Yes, you can use it in comparisons:

IF proc1 = proc2 THEN... (*passive role of the procedure variables*)

Note that after unloading the implementations of the proc1 and proc2, you can still make the comparison. Both proc1 and proc2 are perfectly valid in the passive sense. Their code is gone, but their passive values (addresses) are perfectly OK.

But this is not why procedure variables are important. We want their behaviors. And this gets damaged upon unloading.

In order to cure the problem, the operator :=should not be permitted with procedure variables. There needs to be another, separate operator which will assign procedure variables and also take care of the reference counting.

ASSIGN (procvar, Mod.Proc)

I think that separating both operators := and ASSIGN will make sense, because regular variables are not posing the problem which procedure variables are posing. 

The counterpart of ASSIGN would be RETRACT (or some better name). Since you re not allowed to use := with procedure variables, you could not write 

procvar := NIL; (*not allowed*)

You would have to say 

RETRACT (procvar); (*takes care of the references*)

I hope this proposition makes sense.

W.

----------------------------

Chris, Joerg:

that is exactly the problem: assigning a procedure of a *client* module to a procedure variable of an *imported* module, and then unloading the client module - leaving the procedure variable in the imported module dangling.

Assigning a procedure of a client module to a variable of an imported "base" module is in fact the standard way the Oberon system itself employs procedure variables to implement the viewer system in an object-oriented style.

For example, module TextFrames (the client) installs a handler (procedure TextFrames.Handle) in the field F.handle of text frame F (see TextFrames.NewText and TextFrames.Open for the details), where the record field F.handle is declared as a procedure variable in the "base" module Viewers (see Viewers.ViewerDesc), which also manages the viewer data structure (see procedure Viewers.Open).

Except that of course in the case of the Oberon system, the "client" module TextFrames *never* gets unloaded, so this is not a problem there. Thus, the burden is on the user to make sure that such modules never get unloaded.

It is of course possible to implement a "procedure variable" counter - in analogy to the "module counter" employed in Oberon: each time an assignment to a procedure variable is made, the counter gets increased. But that would require changing the code generator compiler for assignments, and the module loader (Modules.Load) and unloader (Modules.Free). But I would refrain from introducing such complexity to the compiler and runtime system.

Andreas

Chris Burrows chris at cfbsoftware.com <mailto:oberon%40lists.inf.ethz.ch?Subject=Re:%20Re%3A%20%5BOberon%5D%20Oberon%20for%20a%20C%2B%2B%20user.&In-Reply-To=%3C000a01d21ba8%24b97dc9d0%242c795d70%24%40cfbsoftware.com%3E>

________________________________

> Joerg,
>
> OK - you may well be onto something here but it is incomplete as it is. Something has to

> import Square so that the module body is executed, or you need an exported procedure in

> Square that is called from the OS.

>
> Note: there are a couple of semicolons missing and Init must be exported.

>
> Chris.

> -----Original Message-----
> From: Jörg Straube [mailto:joerg.straube at iaeth.ch<https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.inf.ethz.ch_mailman_listinfo_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-ybV0&m=UHr5AP3cXC2ZAXacD2dYANUhpxDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0iN4Zb0ngQ&e=>]
> Sent: Saturday, 1 October 2016 2:22 PM
> To: chris at cfbsoftware.com<https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.inf.ethz.ch_mailman_listinfo_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-ybV0&m=UHr5AP3cXC2ZAXacD2dYANUhpxDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0iN4Zb0ngQ&e=>; ETH Oberon and related systems
> Subject: Re: [Oberon] Oberon for a C++ user.
>
> Chris
>
> Here a possble example that might cause issues:
>
> MODULE Figure;
> TYPE
>   DrawProc = PROCEDURE;
>   Figure = POINTER TO FigureDesc;
>   FigureDesc = RECORD
>     next: Figure;
>     draw: DrawProc
>   END;
> VAR list: Figure;
> PROCEDURE Init(d: DrawProc)
>   VAR f: Figure;
>   BEGIN
>     NEW(f); f.next := list; list := f;
>     f.draw := d
>   END Init;
> BEGIN list:= NIL END Figure.
>
> MODULE Square;
> IMPORT Figure;
> PROCEDURE DrawSquare;
>   BEGIN (* do what ever you
>     need to do to draw a square *)
>   END DrawSquare
> BEGIN
>   Figure.Init(DrawSquare)
> END Square.
>
> Now you could run Square and unload Square. The list in Figure has a
> reference to unloaded code.
>
> J rg
>



More information about the Oberon mailing list