xsharp.eu • And again the old song about REF and NULL
Page 1 of 2

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 8:57 am
by leon-ts
Hello,

Some time ago, the question of a special syntax was discussed, in which VO and Vulcan pass NULL to parameters of functions/methods that accept reference values ​​(REF).

Sample (abstract):

FUNCTION Func1(x AS INT, y AS INT, z REF INT) AS INT

IF (@z) != NULL
z := x * y
ENDIF

RETURN x + y

// Using
SumVal1 := Func1(2, 5, NULL)
SumVal2 := Func1(3, 8, @MultVal)


Vulcan supports this syntax when you include the /vo7 (Compatible Implicit Casts And Conversions) parameter in the project properties.

When can XSharp be expected to support this feature?

After all, it can be maintained virtually in a language. For example, in the process of compiling code in such places, instead of NULL substitute references to real variables (internal, created by the compiler). Or implement this approach even at the stage of code conversion in XPorter.

Now there are two big problems that prevent my enterprise moving from VO to .NET (XSharp). This is the problem described above and the lack of MEMVAR support. The amount of code is huge, it began as early as 1993 and underwent a change from Clipper (DOS) to VO 2.5/2.7/2.8SP3 (Windows). Now 15 programmers work on the project. We need maximum support in XSharp syntax of VO.

Best regards,
Leonid

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 11:41 am
by robert
Leonid,

In VO you can mix REF variables and typed pointers. However these are quit different.
REF variables can never be NULL, typed pointers can.

Vulcan introduced the /vo7 compiler switch. We support that too. This switch allows you to use the typed pointer syntax for reference variables.

An example of a typed pointer

Code: Select all

FUNCTION Func2(x AS INT, y AS INT, z AS INT PTR) AS INT 
IF z != NULL
   z[1] := x * y
ENDIF

RETURN x + y
Finally: MEMVAR support is planned for the X# runtime that we are currently working on.

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 1:00 pm
by Chris
Leonid, Robert,

Had we discussed before that Vulcan does allow even NULL to be passed to REF params? Just like Robert, I thought this is not possible at all, but to my surprise it turns out that it actually is possible, looks like a hack Don had added at some point. We will have a look to see if/how this can be done in x# too and will get back to you. Of course everything else in Robert's post is true, too.

Chris

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 2:00 pm
by leon-ts
Robert, Chris,
Thank you for reply
However these are quit different.
REF variables can never be NULL, typed pointers can.
But nevertheless VO it supports. I can pass NULL and this will work. This is especially true for variables of type STRING. If the parameter is described as AS STRING PTR, communication with GC is lost. In the case of REF, this problem does not occur.

I understand that this behavior in XSharp is somehow related to the limitations of C # (REF and OUT). Therefore, I suggested, can make the necessary replacement in the code at the stage of project import through XPorter?

Sample

Code: Select all

FUNCTION f1(x REF STRING) AS VOID
RETURN
It was:

Code: Select all

f1(@c)
f1(NULL)
Became:

Code: Select all

f1(@c)
LOCAL __null_ref_to_string AS STRING // generated by XPorter
f1(@__null_ref_to_string)
Vulcan introduced the /vo7 compiler switch. We support that too. This switch allows you to use the typed pointer syntax for reference variables.
This I found experimentally. If Vulcan turns off / vo7, the compiler starts to swear by NULL in the REF. If this option is enabled, NULL is allowed and still works correctly (as in VO). Enabling this option in XSharp does not have the same effect.
Had we discussed before that Vulcan does allow even NULL to be passed to REF params?
We did not mention Vulcan last time. Now I drew attention to this only because if in Vulcan a solution for this nuance was found, then it is possible to do this in XSharp.

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 2:36 pm
by Chris
Hi Leonid,

I think this is a big hack done in the vulcan compiler that allows this, I am almost sure that if you test the produced exe/dll containing this compiled code against PEVerify (which checks integrity of .Net code), it will produce all sorts of errors.

But the fact is that it does work, so we'll look into implementing it in x# as well. Vulcan just generates any IL code it wants, while in X# it will be much more difficult to do that, as x# uses the c# backend, which definitely does not allow something like that. But maybe Robert will find a backdoor, will discuss it and will let you know.

If that fails, we will look into implementing what you suggested in VOXporter.

Chris

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 2:42 pm
by leon-ts
Chris, thank you!
I really hope that some of the solutions will be found.

Best regards,
Leonid

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 2:47 pm
by wriedmann
Hi Chris,
If that fails, we will look into implementing what you suggested in VOXporter.
my personal opinion (as I have tons of VO code too):
Please implement that in the XPorter and don't hack the X# compiler.
Then the compiler can check the code and it can eventually been fixed, and it does not leed to problems later at runtime.
IMHO code will be more stable when the XPorter changes the code....

Wolfgang

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 2:58 pm
by robert
Chris,
Chris Pyrgas wrote:
But the fact is that it does work, so we'll look into implementing it in x# as well. Vulcan just generates any IL code it wants, while in X# it will be much more difficult to do that, as x# uses the c# backend, which definitely does not allow something like that. But maybe Robert will find a backdoor, will discuss it and will let you know.
It will not be easy to do this in the compiler.
I have seen some samples that do this, but in that case the function declaration of the function that expects the ref has to be changed.

Another alternative would be to generate a temporary local by the compiler and pass that to the function in stead of the NULL argument. In that case the NULL check inside the function will never be true, since the compiler will then make sure that the reference is valid.


Robert

And again the old song about REF and NULL

Posted: Tue Feb 06, 2018 4:11 pm
by Chris
Robert,
Robert van der Hulst wrote: Another alternative would be to generate a temporary local by the compiler and pass that to the function in stead of the NULL argument. In that case the NULL check inside the function will never be true, since the compiler will then make sure that the reference is valid.
Ah, right, so for the same reason this can't be done in the VOXporter, either, as the proposed change would work for reference types only (as they can be NULL), but not for value types. So this either needs to be implemented in the compiler somehow, or the code must be changed.

Unless it can be implemented with Nullable types? Just thinking aloud here..

Chris

And again the old song about REF and NULL

Posted: Wed Feb 07, 2018 10:21 am
by robert
Leonid,

Code: Select all

FUNCTION Func1(x AS INT, y AS INT, z REF INT) AS INT
    IF (@z) != NULL
        z := x * y
    ENDIF
RETURN x + y
Even in VO this is considered "dirty" syntax. You can only get this to compile when you surround the @z with parentheses like in your example.

If you try it like this:

Code: Select all

FUNCTION Func1(x AS INT, y AS INT, z REF INT) AS INT
    IF @z != NULL
        z := x * y
    ENDIF
RETURN x + y
Then VO will report "bad @ expression".
Having said that: I have implemented a quick fix in the compiler today. Chris will test it and if he sees no side effects then this will be part of the next build.


Robert