fbpx
Welcome, Guest
Username: Password: Remember me
Visual Objects

Please use this forum to post questions about Visual Objects and Vulcan.NET
  • Page:
  • 1

TOPIC: And again the old song about REF and NULL

And again the old song about REF and NULL 1 year 4 months ago #3828

  leon_ts's Avatar Topic Author leon_ts Offline Posts: 13
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

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3831

  robert's Avatar robert Away Posts: 973
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
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.
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Last edit: by robert.

And again the old song about REF and NULL 1 year 4 months ago #3837

  Chris's Avatar Chris Offline Posts: 1149
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
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3840

  leon_ts's Avatar Topic Author leon_ts Offline Posts: 13
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
FUNCTION f1(x REF STRING) AS VOID
RETURN

It was:
f1(@c)
f1(NULL)

Became:
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.

Please Log in or Create an account to join the conversation.

Last edit: by leon_ts.

And again the old song about REF and NULL 1 year 4 months ago #3843

  Chris's Avatar Chris Offline Posts: 1149
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
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3844

  leon_ts's Avatar Topic Author leon_ts Offline Posts: 13
Chris, thank you!
I really hope that some of the solutions will be found.

Best regards,
Leonid

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3845

  wriedmann's Avatar wriedmann Offline Posts: 1549
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
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3846

  robert's Avatar robert Away Posts: 973
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
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3854

  Chris's Avatar Chris Offline Posts: 1149
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
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3859

  robert's Avatar robert Away Posts: 973
Leonid,
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:
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
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Last edit: by robert.

And again the old song about REF and NULL 1 year 4 months ago #3860

  leon_ts's Avatar Topic Author leon_ts Offline Posts: 13
Robert,

I think this is not a "dirty" syntax, but somehow related to the syntax of set/get the value to/from the address stored in the pointer variable.

LOCAL p AS DWORD PTR

Assign an address:
p := 0x12345678 // abstract address

Write the value into memory at the address indicated by the variable:
DWORD(p) := 5 // put the value 5 to the memory at address 0x12345678

Read:
LOCAL n AS DWORD
n := DWORD(p)

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.


Glad to hear. Thank you!

Best regards,
Leonid

Please Log in or Create an account to join the conversation.

Last edit: by leon_ts.

And again the old song about REF and NULL 1 year 4 months ago #3867

  robert's Avatar robert Away Posts: 973
Leonid,

Leonid wrote: Robert,

I think this is not a "dirty" syntax, but somehow related to the syntax of set/get the value to/from the address stored in the pointer variable.

LOCAL p AS DWORD PTR

Assign an address:
p := 0x12345678 // abstract address

Write the value into memory at the address indicated by the variable:
DWORD(p) := 5 // put the value 5 to the memory at address 0x12345678

Read:
LOCAL n AS DWORD
n := DWORD(p)


The DWORD(p) syntax works when p is a pointer and will dereference p and get the data from the address that p points to.

In your example z is a REF INT and not a pointer and therefore "(z)" should be the same as "z", using the general rule that parenthesis operators don't do something special, but are only used to indicate a priority for complex operations.
For example:
LOCAL a, b, c as INT
a := 1
b := 2
c := (a) + (b)   // c will become 3 This is the same as c := a + b
                 // you don't expect any dereferencing here as well.

But apparently VO doesn't work that way, and that is why I called it "dirty".
It was never designed this way, of that I am sure.

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3868

  leon_ts's Avatar Topic Author leon_ts Offline Posts: 13
Robert,

If you write like below the compiler does not produce errors:
FUNCTION Func1(x AS INT, y AS INT, z REF INT) AS INT
    LOCAL p AS INT PTR

    p := @z
    IF (p != NULL)
        z := x * y
        INT(p) := x * y // same result
    ENDIF

RETURN x + y

Here, just one operation is divided into two stages.

p := @z
IF (p != NULL)

And the compiler already perceives this operation as correct.

Best regards,
Leonid

Please Log in or Create an account to join the conversation.

And again the old song about REF and NULL 1 year 4 months ago #3870

  Chris's Avatar Chris Offline Posts: 1149
Hi Leonid,

Yes, this works, as you are creating a pointer to the var yourself. It works only for value types (strutures) though, like INT, LOGIC etc, you can't use that with classes.

In any case, good news is that Robert has already made the necessary changes and the original code compiles fine now! :)
It's looking good so far, nothing else is broken..

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

  • Page:
  • 1