[Oberon] Serious type loophole in type case statements and a possible fix

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Fri Oct 30 17:29:10 CET 2020


    > Yes I agree, as I mentioned in my last email my solution has a cost.
    > If we have to restrict the CASE probably I would rather pay the extra
    > runtime cost or remove this type functionality of the CASE altogether.

Hi Luca,

Our thinking appears to be largely aligned. On the other hand, the restrictions
that I have introduced to the type case statement, namely to disallow “only”

    1. Global case variables p in a case statement CASE p OF .. END                                                                  
    2. Assignments *to* case variables p *within* the scope of a CASE statement                                                    
    3. Passing a pointer case variable p as a VAR parameter to a procedure P(p)
                                                                                                                                            
don’t seem to be all too severe after all - as I can compile the entire Oberon
system (and in fact any other module that I have ever seen). These 3 cases
just don’t seem to be used much in practice. For good reasons probably.

In particular, passing a *record* case variable r, which is *itself* a VAR parameter,
as a VAR parameter to another procedure P *is* safe and is therefore *allowed*
in my solution. 

This covers the important case of a typical handler procedure in
the Oberon viewer system, for example in MenuViewers:

 PROCEDURE Handle* (V: Display.Frame; VAR M: Display.FrameMsg);
    VAR Menu, Main: Display.Frame;
  BEGIN Menu := V.dsc; Main := V.dsc.next;
      CASE M OF
      Oberon.InputMsg:
        IF M.id = Oberon.track THEN
          ...
        ELSE Menu.handle(Menu, M); Main.handle(Main, M)
        END |
      ...
      END
  END Handle;

Here M is a VAR parameter of a record type and is simply “passed on"
- again as a VAR parameter M - to the handlers of the 2 subframes:

   Menu.handle(Menu, M); Main.handle(Main, M)

where Main.handle and Menu.handle is TextFrames.Handle

  PROCEDURE Handle* (F: Display.Frame; VAR M: Display.FrameMsg);

Now, this particular handler doesn’t actually make an assignment to M, 
but even if it did (M := M1, where M1 is a record of an extended type),
it would be completely “safe”.

Because the assignment M := M1 is just a “projection" (of the fields of
M1 onto the fields of M) and doesn’t change the runtime type of M.

And this is what convinced me to retain the type case statement
(with the above restrictions). It’s pretty efficient.

Andreas



More information about the Oberon mailing list