[Oberon] Dynamic type of record var parameter

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Tue Jan 12 07:23:40 CET 2021

    > VAR p : p0;  r : r0; q : p2; t : r2;
    >	p := q;  check(p^);

This is a known issue in the Project Oberon 2013 compiler:
It just does *not* handle the case where the actual parameter
of a procedure is a dereferenced pointer p^.

PS: The Ceres-Oberon compiler handled this correctly (‘wasderef'):

    PROCEDURE Param*(VAR ap: OCT.Item; f: OCT.Object);
    ELSIF (.. (ap.mode = RegI)) & (ap.obj = OCC.wasderef)  (*<--*)
    THEN (*actual par is p^*) … 

To fix this in the Project Oberon 2013 compiler, one would first
need to “remember”, whether a procedure parameter has in fact
been dereferenced or not. That part is easy: you just do so,
e.g. by keeping track of calls to ORG.DeRef in ORP.selector:

PROCEDURE selector(VAR x: ORG.Item;
    VAR …; deref: BOOLEAN;  (*keeps track of dereferenced pointers*)
  BEGIN deref := FALSE;
    WHILE (sym = ORS.lbrak) OR (sym = ORS.period) OR (sym = ORS.arrow)
        OR (sym = ORS.lparen) & (x.type.form IN {ORB.Record, ORB.Pointer}) DO
      IF sym = ORS.lbrak THEN
        Check(ORS.rbrak, "no ]”); deref := FALSE
      ELSIF sym = ORS.period THEN ORS.Get(sym);
        IF sym = ORS.ident THEN
          IF x.type.form = ORB.Pointer THEN ORG.DeRef(x); x.type := x.type.base; deref := TRUE END ;
          IF x.type.form = ORB.Record THEN
            IF obj # NIL THEN ORG.Field(x, obj); x.type := obj.type; deref := FALSE ELSE … END
      ELSIF sym = ORS.arrow THEN
        IF x.type.form = ORB.Pointer THEN ORG.DeRef(x); x.type := x.type.base; deref := TRUE
  END selector;

The problem now is how to *store* the value of “deref" in the item x
itself. In Ceres-Oberon, the field x.obj was “abused” for this purpose.

But when transitioning from Ceres-Oberon to PO2013-Oberon, several
item fields were eliminated, among them also the back pointer field
x.obj. So the baby was flushed down with the washing water.. ;-)

Unfortunately, there is no other item field that one could use to encode
the fact that an item x has been dereferenced (all fields are taken),
so one would need to add back one, e.g. an extra field x.c.

Assuming this is done, one could then use this field in ORG.VarParam,
similar to how the Ceres Oberon compiler does it in OCH.Param:

PROCEDURE VarParam*(VAR x: Item; ftype: ORB.Type);
    VAR xmd: INTEGER;
  BEGIN xmd := x.mode; loadAdr(x);
    IF (ftype.form = ORB.Array) & (ftype.len < 0) THEN (*open array*)
    ELSIF ftype.form = ORB.Record THEN
      IF x.c > 0 THEN (*deref*) (*use dynamic type, not static type*) ... END
  END VarParam;

There are other ways to solve this, for example by introducing
another VAR parameter “deref” to ORP.selector:

   PROCEDURE selector(VAR x: ORG.Item; VAR deref: BOOLEAN);

to pass around the value of deref within the compiler. But then one
would need to also add the same parameter in several other places
in the compiler as well, e.g. expression/term/factor…

It can all be done, but it just hasn’t. Perhaps someone finds a
more elegant way of handling this case..

Any takers??

More information about the Oberon mailing list