lboasso / oberonc

An Oberon-07 compiler for the JVM

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect Handling of Pointer Type Base and Incompatible Assignment

geekstakulus opened this issue · comments

Introduction

In Oberon-07, two pointer types are considered equal if they have the same base type. Consequently, if a record field is declared as a pointer to a specific type, and later another type is declared as a pointer to the same base type, both types should be equal and assignment compatible.

Current Behavior

Consider the following code snippet:

MODULE PointerCompat;
  TYPE
    Rec = RECORD
      x, y : INTEGER;
    END;

    PRec1 = POINTER TO Rec;
    PRec2 = POINTER TO Rec;

  VAR
    p1 : PRec1;
    p2 : PRec2;
BEGIN
  NEW(p1);
  p2 := p1;
  p2.x := 12;
  p2.y := 10;
  ASSERT(p1 = p2);
  ASSERT(p1.x = p2.x);
  ASSERT(p1.y = p2.y)
END PointerCompat.

In this example, PRec1 and PRec2 are equal types and assignment compatible, which is expected behavior.

However, when declaring a record with a field of type POINTER TO Rec and subsequently attempting to assign it to a variable declared as POINTER TO Rec, as shown below:

MODULE PointerCompat2;
  IMPORT Out;
  TYPE
    Rec = RECORD
      x, y : INTEGER;
      next : POINTER TO Rec
    END;

    PRec1 = POINTER TO Rec;
    PRec2 = POINTER TO Rec;

  VAR
    p1 : PRec1;
    p2 : PRec2;
    p : PRec1;
BEGIN
  NEW(p1);
  NEW(p2);
  p1.x := 13;
  p1.y := 19;
  p1.next := p2;
  p2.x := 12;
  p2.y := 10;
  
  p := p1;
  WHILE p # NIL DO
    Out.String("x = "); Out.Int(p.x, 0); Out.Ln;
    Out.String("y = "); Out.Int(p.y, 0); Out.Ln;
    p := p.next
  END
END PointerCompat2.

The compiler reports the following errors:

PointerCompat2.Mod:16:0: undefined pointer base: END
PointerCompat2.Mod:21:16: illegal assignment
PointerCompat2.Mod:30:0: illegal assignment
PointerCompat2.Mod:31:19: compilation FAILED

The compiler does not recognize the pointer base of PRec1 declared as the type of variable p. Consequently, it does not recognize the assignment of a variable of type POINTER TO Rec, which is the same as the one defined for the field next of Rec.

The issue is resolved when the field next is defined with a pre-declared pointer type, as demonstrated in the following code:

MODULE PointerCompat3;
  IMPORT Out;
  TYPE
    PRec1 = POINTER TO Rec;
    PRec2 = POINTER TO Rec;
    Rec = RECORD
      x, y : INTEGER;
      next : PRec1
    END;

  VAR
    p1 : PRec1;
    p2 : PRec2;
    p : PRec1;
BEGIN
  NEW(p1);
  NEW(p2);
  p1.x := 13;
  p1.y := 19;
  p1.next := p2;
  p2.x := 12;
  p2.y := 10;
  
  p := p1;
  WHILE p # NIL DO
    Out.String("x = "); Out.Int(p.x, 0); Out.Ln;
    Out.String("y = "); Out.Int(p.y, 0); Out.Ln;
    p := p.next
  END
END PointerCompat3.

Expected Behavior

The compiler should successfully compile the code, regardless of whether record fields are declared with a pre-declared pointer type or directly as a pointer to the same type.

Repro Steps

  1. To observe this behavior:
    1. Compile the code in the three examples using the Oberonc compiler.
    2. Note that the compiler successfully compiles the code for PointerCompat.Mod and PointerCompat3.Mod, but reports errors for PointerCompat2.Mod.

Other Information

This issue has not been tested with the original compiler. However, when compiled with OBNC, it does not present this problem and behaves as expected.

It looks like the scanner is out of sync, indeed the error points to keyword END and the compiler assumes it is a type.
Thanks for reporting this, I'll push a fix soon.

OK, take your time. It isn't something urgent, but it is good that I caught it. There is no better way to catch bugs in a compiler than to write pretty bad code. LoL

Fixed.
Thanks again for the great bug reports! I really appreciate it!

Thanks for the quick fix! As usual, you are always fast at fixing bugs.

All working!