vishapoberon / compiler

vishap oberon compiler
http://oberon.vishap.am
GNU General Public License v3.0
186 stars 25 forks source link

Error in WITH statement with pointers to related type extended records #98

Open tkurtbond opened 1 year ago

tkurtbond commented 1 year ago

When I compile the following program with Vishap Oberon:

MODULE example;

  IMPORT Out;

  TYPE
    (** A rope. *)
    T* = POINTER TO TDesc;
    TDesc = RECORD
    END;

    (** Alias for type Rope.T. *)
    Rope* = T;

    PAoC = POINTER TO ARRAY OF CHAR;

    SubNode = POINTER TO SubDesc;
    SubDesc = RECORD (TDesc)
      s: PAoC;
      start: LONGINT;
      length: LONGINT;
    END;

    CatNode = POINTER TO CatDesc;
    CatDesc = RECORD (TDesc)
      height: LONGINT;
      length: LONGINT;
      left: T;
      leftLength: LONGINT;
      right: T;
    END;      

    PROCEDURE print (r: T);
    BEGIN
      Out.Char ('(');
      WITH r: SubNode DO
        Out.String ('SubNode: start: '); Out.Int (r.start, 0);
        Out.String (' length: '); Out.Int  (r.length, 0);
      | r: CatNode DO
        Out.String ('CatNode: height: '); Out.Int (r.height, 0);
        Out.String (' length: '); Out.Int (r.length, 0);
        Out.String (' leftLength: '); Out.Int (r.leftLength, 0);
        Out.String (' left: ');
        print (r.left);
        Out.String (' right: ');
        print (r.right);
      ELSE
        Out.String ('Length: impossible error: r is not SubNode or CatNode'); Out.Ln;
      END;
      Out.Char (')');
    END print;

END example.

I get this error:

voc -f example.Mod -m
example.Mod  Compiling example.

  43:         print (r.left);
                          ^
    pos   985  err 113  incompatible assignment

  45:         print (r.right);
                           ^
    pos  1043  err 113  incompatible assignment

Module compilation failed.

Both of the other Oberon-2 compilers I tried with (oo2c and obc) compiled this without error, but I can't use either of them for the project from which this example is extracted (oo2c has a bug that makes the project fail, for instance).

norayr commented 1 year ago

Thank you for raising this issue.

I am thinking about this. Most probably we have a bug which needs to be fixed, but hang on, I am investigating this.

It's interesting, I tried your source in OLR, and it's version of OP2 parser was not able to compile it because of different issue - the parser didn't agree with the usage of the pipe (|) symbol, though it seems to be correct Oberon-2 syntax. It said - END expected.

Anyway that didn't directly relate to the actual question of using print (r.left) so I changed the source a little bit, and it was able to compile it.

However voc is inherited from the different line - Linz's version of parser, it would be interesting to see how that compiler would behave. But I cannot, because Oberon V4 for Linux was linked to the old version of glibc (OLR doesn't use libc at all) and is not usable nowadays. Though I have a friend who revived it, extended it, and has a running copy on FreeBSD.

tkurtbond commented 1 year ago

Is your friend’s revived version of Oberon V4 something that is publicly available? I’d be interested…

MarkowEduard commented 1 year ago

This problem is well known and dates back to the early releases of OP2 by Crelier Regis from the ETH. The reason for the problem is that the WITH statement changes the type of the variable which is in this case a parameter and therefore the type of the procedure is changed.

A simple workaround is to deliberately adjust the type of the supplied parameter:

    print (r.left(CatNode));
    ...
    print (r.right(CatNode));
norayr commented 1 year ago

@MarkowEduard thank you so much!

@tkurtbond will that work for you till i'll fix the parser? because with my current load it'll take time.

tkurtbond commented 1 year ago

@MarkowEduard thank you so much!

@tkurtbond will that work for you till i'll fix the parser? because with my current load it'll take time.

That will work fine! Thank you, and @MarkowEduard!

tkurtbond commented 1 year ago

@tkurtbond will that work for you till i'll fix the parser? because with my current load it'll take time.

That will work fine! Thank you, and @MarkowEduard!

I spoke too soon: that let the example I'd extracted from the real module compile fine, and the real module compiled fine, but it died with a HALT(-5) type guard failed. However, the phrase "and therefore the type of the procedure is changed" did lead to a workaround that does work: I introduced a variable t: T and set t to r, and used t in the WITH instead of r. That way the type of the procedure doesn't get changed, if I understand correctly.

Again, thanks @MarkowEduard and @norayr!

MarkowEduard commented 1 year ago

Can you provide an example?