FreeBASIC syntax challenge games

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

fxm wrote:Pseudo-code for the particular solution (function returning a reference to the instance on which it was called):
  • Cast(Base_Type, derived_instance) = Base_Type(derived.instance).overridden_function()
Maybe this line of code equivalent to the one above, but formalized with a slightly different syntax, will speak to you more:
  • Cast(Base_Type, derived_instance) = Type<Base_Type>(derived.instance).overridden_function()
The idea is to create a temporary copy of the derived instance, and to call the function on it.
=> one single code line.

[edit]
Posting the adding in a new post.
Last edited by fxm on Oct 31, 2017 13:46, edited 2 times in total.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBASIC syntax challenge games

Post by dodicat »

You have more or less given the solution.
Cast(parent,c) = Type<parent>(c).dec

Which I checked on -gen gcc.

Grindstone solved the previous one well, and sancho2 contributed a while back with a solution for another.
I don't mind having a try now and then, although I am not very good.
But failing miserably is no problem for me.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

When a Type directly or indirectly derives from the built-in type Object, compiler adds an implicit default-constructor and implicit copy-constructor to the Type whatever its own fields or inherited fields.
(both 'Base_Type(derived.instance)' and 'Type<Base_Type>(derived.instance)' calling the copy-constructor to create a temporary copy)
Last edited by fxm on Oct 31, 2017 20:49, edited 2 times in total.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

dodicat wrote:Grindstone solved the previous one well, and sancho2 contributed a while back with a solution for another.
I don't mind having a try now and then, although I am not very good.
But failing miserably is no problem for me.
The most important is not the solution in itself, but especially all the paths taken to try to get there.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Enigma #25, force 5 (successive clues could be given to lower the level of difficulty)
Macro to determine if any Type (including pre-defined types and user defined types) has a destructor (explicit or implicit).

Fill in the macro definition ('TypeHasDtor()') of the code below, which from a passed symbol name for a Type ('Typesymbol') assigns the value of a passed Boolean variable ('TypeHasDtorResult') as 'True' or 'False' depending of the existence of a destructor for the corresponding Type:

Code: Select all

#macro TypeHasDtor(TypeSymbol, TypeHasDtorResult)
    '' Determine if the Type has a destructor (implicit or explicit).
    
    '' TypeSymbol must be a symbol name referring to a Type (built-in or UDT).
    ''    (either the Type name itself if it's a symbol name, or an alias)
    
    '' TypeHasDtorResult must be a Boolean variable.
    ''    (or an integer numeric variable)
    
    '' ------------------------------------------------------------------------
    ' Insert here the definition code of the macro:
    ' .....
    ' .....
    ' .....
    ' TypeHasDtorResult = ...
    '' ------------------------------------------------------------------------
#endmacro


Dim As Boolean hasDtorResult

TypeHasDtor(Integer, hasDtorResult)
Print "The 'Integer' Type has a destructor (implicit or explicit): ", hasDtorResult

TypeHasDtor(String, hasDtorResult)
Print "The 'String' Type has a destructor (implicit or explicit): ", hasDtorResult

Type string10Type As String * 10  '' define an alias to get a symbol name
TypeHasDtor(string10Type, hasDtorResult)
Print "The 'String * 10' Type has a destructor (implicit or explicit): ", hasDtorResult

Type stringptrType As String Ptr  '' define an alias to get a symbol name
TypeHasDtor(stringptrType, hasDtorResult)
Print "The 'String Ptr' Type has a destructor (implicit or explicit): ", hasDtorResult

TypeHasDtor(Object, hasDtorResult)
Print "The 'Object' Type has a destructor (implicit or explicit): ", hasDtorResult

Type UDT1 Extends Object
End Type
TypeHasDtor(UDT1, hasDtorResult)
Print "The 'UDT1' User-Type has destructor (implicit or explicit): ", hasDtorResult

Type UDT2 Extends Object
    Declare Destructor ()
End Type
Destructor UDT2 ()
End Destructor
TypeHasDtor(UDT2, hasDtorResult)
Print "The 'UDT2' User-Type has destructor (implicit or explicit): ", hasDtorResult

Sleep
My full solution for defining this macro is a code of 16 simple lines (no concatenated instructions on the same line with ':').

Expected output for the above test case (but must work for any Type):

Code: Select all

The 'Integer' Type has a destructor (implicit or explicit):           false
The 'String' Type has a destructor (implicit or explicit):            true
The 'String * 10' Type has a destructor (implicit or explicit):       false
The 'String Ptr' Type has a destructor (implicit or explicit):        false
The 'Object' Type has a destructor (implicit or explicit):            false
The 'UDT1' User-Type has destructor (implicit or explicit):           false
The 'UDT2' User-Type has destructor (implicit or explicit):           true
[edit]
- First clue lowering Enigma #25 to force 4: When a Type has a destructor (explicit or implicit), NEW [] adds an Integer in front of the user instances block to store the number of allocated elements, so that DELETE [] can call the destructor on each element.
- Second clue lowering Enigma #25 to force 3: The macro principle is to apply the New [] operator on an UDT containing a single data member of the Type to test, and to safely check if an Integer (to store the number of instances to destroy) is added ahead the user instances block in the allocated memory. Consequently, the address of the user instances block is different from that of the global allocated memory.
- Third clue lowering Enigma #25 to force 2: To resolve this, the simpler is to define in the UDT an overload operator DELETE [] (a similar method could have been used by defining this time an overload operator NEW []).
- Forth (and last) clue lowering Enigma #25 to force 1: The address of the global memory that the overload operator NEW [] must deallocate is passed to it (under the hood) as a parameter. So, one just has to also store it to later can compare it to the known address of the user instances block (the overload operator being static has no access to the THIS reference).
  • Note:
    - When one adds an overload operator NEW or NEW [], a parameter gives the number of byte to allocate, and the operator must return the allocated memory address.
    - When one adds an overload operator DELETE or DELETE [], a parameter gives the memory address to deallocate.

Last edited by fxm on Jan 05, 2020 6:43, edited 8 times in total.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Added a first clue to the enigma #25 of post viewtopic.php?p=267129#p267129.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBASIC syntax challenge games

Post by dodicat »

I'll start this off.

Code: Select all




#macro TypeHasDtor(TypeSymbol, TypeHasDtorResult)

     type udt##typesymbol 
        as typesymbol  x
        declare function show as integer
    end type
    
    function udt##typesymbol.show as integer
    return cast(integer ptr,cast(any ptr ,@this))[-1]
    end function
    
    var Num##typesymbol=5 'an arbitary number of instances
    dim as udt##typesymbol ptr p##typesymbol=new udt##typesymbol[Num##typesymbol]
    TypeHasDtorResult=iif(p##typesymbol->show=Num##typesymbol,true,false)
    if TypeHasDtorResult = false then delete[] p##typesymbol
   
    '' ------------------------------------------------------------------------
#endmacro


Dim As boolean hasDtorResult

TypeHasDtor(Integer, hasDtorResult)
Print "The 'Integer' Type has a destructor (implicit or explicit): ", hasDtorResult

TypeHasDtor(String, hasDtorResult)
Print "The 'String' Type has a destructor (implicit or explicit): ", hasDtorResult

Type string10Type As String * 10  '' define an alias to get a symbol name
TypeHasDtor(string10Type, hasDtorResult)
Print "The 'String * 10' Type has a destructor (implicit or explicit): ", hasDtorResult

Type stringptrType As String Ptr  '' define an alias to get a symbol name
TypeHasDtor(stringptrType, hasDtorResult)
Print "The 'String Ptr' Type has a destructor (implicit or explicit): ", hasDtorResult

TypeHasDtor(Object, hasDtorResult)
Print "The 'Object' Type has a destructor (implicit or explicit): ", hasDtorResult

Type UDT1 Extends Object
End Type
TypeHasDtor(UDT1, hasDtorResult)
Print "The 'UDT1' User-Type has destructor (implicit or explicit): ", hasDtorResult

Type UDT2 Extends Object
    Declare Destructor ()
End Type
Destructor UDT2 ()
End Destructor
TypeHasDtor(UDT2, hasDtorResult)
Print "The 'UDT2' User-Type has destructor (implicit or explicit): ", hasDtorResult

Sleep 
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Your proposal is a good start and reveals my second clue which I have now added in my initial post (see viewtopic.php?p=267129#p267129), lowering the force to 3.

But your proposal is not fully safe because when the Type has no destructor, you access a memory which is not allocated and the program may hang.
(my solution does not access this memory)

Remark on your code end:
'delete[] p##typesymbol' must always be executed, whatever the Type check result.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

fxm wrote:Your proposal is a good start and reveals my second clue which I have now added in my initial post (see viewtopic.php?p=267129#p267129), lowering the force to 3.

But your proposal is not fully safe because when the Type has no destructor, you access a memory which is not allocated and the program may hang.
(my solution does not access this memory)
Added a short sentence to the second clue in order to suggest the safe test method to be used.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: FreeBASIC syntax challenge games

Post by Tourist Trap »

fxm wrote:]Your proposal is a good start and reveals my second clue which I have now added in my initial post (see viewtopic.php?p=267129#p267129), lowering the force to 3.
Hi fxm,

I don't claim being right, but while making a modest try, here I found something I found funny as a matter of fact:
error 164: Fields with destructors cannot be part of UNION's or nested TYPE's in 'as UDT ayeaye'

Code: Select all

union X
   type
      as integer     thingy
      as integer     ayeaye
   end type
end union

dim as X xx
xx.thingy = 0
scope
   xx.ayeaye = 100
   ? xx.thingy
end scope
? xx.thingy


type UDT
   declare destructor()
   as integer ii
end type
destructor UDT()
   this.ii = -1
end destructor


union Y
   type
      as integer     thingy
      as UDT         ayeaye
   end type
end union

dim as Y yy
yy.thingy = 0
scope
   dim as UDT yy.ayeaye
   ? yy.thingy
end scope
? yy.thingy
We can't really catch the error at runtime of course so it seems not good. But would you discourage the UNION way?
I'm assuming that passing out of the scope bloc will trigger the destructor, and that it will leave a track on the reserved space in front of the variable (it's how I interpret the dodi's proposal --> return cast(integer ptr,cast(any ptr ,@this))[-1]).
Just a try of course ;)
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Tourist Trap wrote: We can't really catch the error at runtime of course so it seems not good. But would you discourage the UNION way?
More simply, if an UDT has a destructor (explicit or implicit), the destructor can be called on any UDT instance 'u':
u.Destructor() 'compiles
otherwise, compilation error.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: FreeBASIC syntax challenge games

Post by Tourist Trap »

fxm wrote:More simply, if an UDT has a destructor (explicit or implicit), the destructor can be called on any UDT instance 'u':
u.Destructor() 'compiles
otherwise, compilation error.
I see.

So I think I get it (still not with the macro but can see that after). This returns 1:

Code: Select all

type DESTRUCTABLE_UDT
   declare destructor()
   as integer ii
end type
destructor DESTRUCTABLE_UDT()
   this.ii = -1
end destructor

dim as DESTRUCTABLE_UDT ptr du => new DESTRUCTABLE_UDT[1]
? *cast(integer ptr, du - 1)
Are we on the right path?

Other sample:

Code: Select all

type DESTRUCTABLE_UDT
   declare destructor()
   as integer ii
end type
destructor DESTRUCTABLE_UDT()
   this.ii = -1
end destructor

dim as DESTRUCTABLE_UDT ptr du => new DESTRUCTABLE_UDT[1]
? *cast(integer ptr, du - 1)

'--> 1

dim as OBJECT ptr ob => new OBJECT[1]
? *cast(integer ptr, ob - 1)

'--> a big num

dim as DESTRUCTABLE_UDT ptr duu => new DESTRUCTABLE_UDT[1]
? *cast(integer ptr, duu - 1)

'--> 1
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Yes, but it is the same method than the dodicat's proposal: not safe.
(if there is no destructor, this accesses an un-allocated memory)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: FreeBASIC syntax challenge games

Post by Tourist Trap »

fxm wrote:Yes, but it is the same method than the dodicat's proposal: not safe.
(if there is no destructor, this accesses an un-allocated memory)
Ah yes...
So what about this? getting, ice or warmer ?

Code: Select all

type TEST
   as DESTRUCTABLE_UDT uu
end type

dim as TEST ptr tt = new TEST[1]
? *cast(integer ptr, @(tt->uu) - 1)
delete[] tt
? *cast(integer ptr, @(tt->uu) - 1)

type TEST2
   as OBJECT oo
end type

dim as TEST2 ptr tt2 = new TEST2[1]
? *cast(integer ptr, @(tt2->oo) - 1)
delete[] tt2
? *cast(integer ptr, @(tt2->oo) - 1)
The idea I have is that there is a reserved (safe) room for an integer there since we are in the TEST UDT, but not quite sure.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Tourist Trap wrote: The idea I have is that there is a reserved (safe) room for an integer there since we are in the TEST UDT, but not quite sure.
No.

In addition, your 'Cast' expression is wrong in general case.
One correct is:
? cast(integer ptr, @(tt->uu))[-1]
or better:
? cast(integer ptr, tt)[-1]
Post Reply