X-Sharp / XSharpPublic

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

memvar.xh Preprocessor problem #71

Closed Karl1155 closed 5 years ago

Karl1155 commented 5 years ago

The memvar.xh RELEASE command creates wrong params e.g. ( "gc1,gc2") instead of ( "gc1" , "gc2" ) which results in a runtime error.

#INCLUDE "memvar.xh"

// the memvar.xh RELEASE command creates wrong params e.g. ( "gc1,gc2") instead of ( "gc1" , "gc2" ) 
// which results in a runtime error.
// #command RELEASE <vars,...>             => _MXRelease( <"vars"> )
//
// This replaces the faulty X#  RELEASE command.  
#COMMAND RELEASE <var1> [, <varN> ] => _MXRELEASE(#<var1> [, #<varN> ])   // see VO - STD.UDC  

// compiler settings:  -memvar+   -undeclared+ -ppo+

FUNCTION Start() AS VOID
PUBLIC gc1, gc2 
PRIVATE p1, p2 

? gc1  //ok, false
? gc2  //ok, false
? p1   //ok, NIL 
? p2   //ok, NIL 

RELEASE gc1, gc2
RELEASE p1, p2 

// NOTE: since the 2.0.2.0 build the memvars are being "destroyed" - as Foxpro does.

// ? gc1   // ok, would throw an runtime error
// ? p1    // ok, would throw an runtime error

RETURN 

/*
How should the X# Match and X# Result marker look like if the result of:
RELEASE gc1, gc2 
must be:
_MXRelease ( "gc1" , "gc2" )

I think the X# Match marker <vars,...> is ok, but the Result marker ?
=> _MXRelease( ???? ) 
i´ve tried => _MXRelease( [<vars>] ) but that results in _MXRelease ( gc1 , gc2 ). 
I´ve tried in the result marker at several places " , 
i´ve also looked in the "Command-Translate" X# help section, 
but i´m not able to get the result _MXRelease ( "gc1" , "gc2" ) ?
*/
RobertvanderHulst commented 5 years ago

Karl, This MEMVAR area is a bit of a challenge.

Karl1155 commented 5 years ago

Hi Robert,

i´ve also tried the other RELEASE commands:

PUBLIC gc1, gc2 
PRIVATE p1, p2, x1 

gc1  := "gc1" 
gc2  := "gc2" 
p1  := "p1"   
p2  := "p2"   
x1  := "x1"

RELEASE ALL LIKE p*
RELEASE ALL LIKE g*
RELEASE ALL EXCEPT p2

The behaviour of these commands is the same as VO shows. PUBLICs are not touched, only the PRIVATE values are changed to NIL. But Foxpro would "destroy" the PRIVATES and the PUBLICs instead. Because a single RELEASE <cVar>, ... currently "destroys" PRIVATES and PUBLICS shouldn´t the RELEASE ALL xxx commands behave the same - because we are currently in the Foxpro mode ;-) ?

Very strange is the result of the command:

RELEASE ALL

it´s translated to:

_MXRELEASE("ALL" )

When I look at the order of the memvar.xh content, it seems that in this case the precompiler simply picks up the very first RELEASE command:

...
#command CLEAR MEMORY                   => _MClear()
#command RELEASE <vars,...>             => _MXRelease( <"vars"> )
#command RELEASE ALL                    => _MRelease("*", TRUE)
#command RELEASE ALL LIKE <skel>        => _MRelease( #<skel>, TRUE )
#command RELEASE ALL EXCEPT <skel>      => _MRelease( #<skel>, FALSE )
...

Tomorrow i'll take a look at the SAVE and RESTORE commands and report back again when there are problems.

regards Karl-Heinz

RobertvanderHulst commented 5 years ago

Mmm, That looks like either a bug in the PP definition or in the PP itself. I'll check

RobertvanderHulst commented 5 years ago

Maybe you can look at the source of the MEMVAR support and suggest a fix. I'm quite busy now with other things. It's in https://github.com/X-Sharp/XSharpPublic/blob/feature/Runtime/Runtime/XSharp.RT/Types/MemVar.prg and https://github.com/X-Sharp/XSharpPublic/blob/feature/Runtime/Runtime/XSharp.RT/Functions/MemVar.prg

and the save/restore stuff is in

https://github.com/X-Sharp/XSharpPublic/blob/feature/Runtime/Runtime/XSharp.RT/Functions/MemVarSave.prg

Karl1155 commented 5 years ago

Robert,

I post some results to be sure that they don´t get lost ;-)

i made some test to see how PRIVATEs - with the same name and declared in different areas - are released . Below are the VO,X#, CLIPPER and Foxpro results. From what i see, FP, CLIPPER and VO behave in all 4 scenarios the same. The only difference is that FP destroys a PRIVATE while the other two assign NIL. As you see X# does too much in the scenario 2 and 3.

FUNCTION Start() AS VOID
PRIVATE p1, p2

 p1:= "p1 Start()"
 p2:= "p2 Start()"

 Test2() 

 ? 
 ? "p1 Start():" , p1   
 ? "p2 Start():" , p2         
 ? 

RETURN 

PROCEDURE Test2
PRIVATE p1, p2  

  p1 := "p1 Test2()"
  p2 := "p2 Test2()"

  Test3()   

?  
? "p1 Test2():" , p1 
? "p2 Test2():" , p2      
?  

RETURN  

PROCEDURE Test3
PRIVATE p1, p2 

  p1 := "p1 Test3()"
  p2 := "p2 Test3()"

// RELEASE ALL LIKE p*
_MRelease( "p*" , TRUE ) 

?
? "p1 Test3():" , p1 
? "p2 Test3():" , p2      
?

RETURN  

1) The unchanged code shows the result:

// -- VO + X# + Foxpro + clipper -----

p1 Test3(): NIL // FP destroys the memvar p1 instead 
p2 Test3(): NIL // FP destroys the memvar p2 instead  

p1 Test2(): p1 Test2()
p2 Test2(): p2 Test2()

p1 Start(): p1 Start()
p2 Start(): p2 Start()

2) If in addition the line "private p1, p2" in the Test3() proc is deactivated the results are:

// -- Foxpro + VO + clipper --

p1 Test3(): p1 Test3()
p2 Test3(): p2 Test3()

p1 Test2(): p1 Test3()
p2 Test2(): p2 Test3()

p1 Start(): p1 Start()
p2 Start(): p2 Start()

// ----- X# ---------

p1 Test3(): NIL
p2 Test3(): NIL

p1 Test2(): NIL
p2 Test2(): NIL

p1 Start(): p1 Start()
p2 Start(): p2 Start()

3) If in addition the line "private p1, p2" in the Test2() proc is deactivated the results are:

// ---- VO + Foxpro + clipper -----

p1 Test3(): p1 Test3()
p2 Test3(): p2 Test3()

p1 Test2(): p1 Test3()
p2 Test2(): p2 Test3()

p1 Start(): p1 Test3()
p2 Start(): p2 Test3()

// ---- X# ---------- 

p1 Test3(): NIL
p2 Test3(): NIL

p1 Test2(): NIL
p2 Test2(): NIL

p1 Start(): NIL
p2 Start(): NIL

4) If only the line "private p1, p2" in the Test2() proc is deactivated the results are:

// --- VO + Foxpro + X# + clipper -----

p1 Test3(): NIL // NOTE: FP destroys the memvar p1 instead 
p2 Test3(): NIL // NOTE: FP destroys the memvar p2 instead 

p1 Test2(): p1 Test2()
p2 Test2(): p2 Test2()

p1 Start(): p1 Test2()
p2 Start(): p2 Test2()