X-Sharp / XSharpPublic

Public repository for the source code for the XSharp Compiler, Runtime, Project System and Tools.
Apache License 2.0
91 stars 36 forks source link

VO incompatibility resolving GLOBALs/DEFINEs #1521

Open cpyrgas opened 1 month ago

cpyrgas commented 1 month ago

https://www.xsharp.eu/forum/topic?p=30408#p30408

Following should probably apply only to the VO dialect, and let other dialects handle this differently.

In VO, when there's a name ambiguity, the compiler resolves identifiers used inside a class in this order:

  1. Class fields
  2. GLOBAL/DEFINE
  3. Class ACCESS/ASSIGN

In X#, currently it resolves to ACCESS/ASSIGN before GLOBAL/DEFINE, causing unintended recursive calls

The following code compiles with no errors in VO, except for the two lines that are supposed to produce one. In X#, it's the opposite:

/*
prg(25,3): error XS0154: The property or indexer 'NewTest.dTest2' cannot be used in this context because it lacks the get accessor
prg(26,3): error XS0200: Property or indexer 'NewTest.gTest2' cannot be assigned to -- it is read only
prg(32,3): error XS0154: The property or indexer 'NewTest.dTest2' cannot be used in this context because it lacks the get accessor
prg(33,3): error XS0200: Property or indexer 'NewTest.gTest2' cannot be assigned to -- it is read only
*/

GLOBAL gTest1 := "global"
DEFINE dTest1 := "define"

GLOBAL gTest2 := "global"
DEFINE dTest2 := "define"

CLASS NewTest
    EXPORT gTest1 := "class"
    EXPORT dTest1 := "class"
    METHOD TestMethod()
        ? gTest1
        ? dTest1
        gTest1 := "class modified"
        ? gTest1

        dTest1 := "class modified"
        ? dTest1

        dTest2 := "should report compiler error since it refers to a define" // error in VO, no error in X#
    RETURN NIL

    ACCESS gTest2()
        ? gTest2
        ? dTest2 // error in X#
        gTest2 := "global modified" // error in X#
        ? gTest2
    RETURN "access"

    ASSIGN dTest2(u)
        ? gTest2
        ? dTest2 // error in X#
        gTest2 := "global modified again" // error in X#
        ? gTest2

        dTest2 := "should report compiler error since it refers to a define" // error in VO, no error in X#
END CLASS

FUNCTION Start() AS VOID
    LOCAL o AS NewTest
    o := NewTest{}
    o:TestMethod()
    ? "-----------"
    ? o:gTest2
    ? "-----------"
    gTest2 := "global"
    o:dTest2 := "test"
cpyrgas commented 1 month ago

The fix for this will need to be tested also in conjunction with the /enforceself option. Not that in VO it is always mandatory to use SELF: for accessing methods and access/assigns. but not for class fields!!! In X# when enabling this option it requires SELF: everywhere, and I think we should keep it this way.

cpyrgas commented 1 month ago

Also note that GLOBALs/DEFINEs should be resolved before properties (but still after class fields) even if they are defined in a separate library.