FreeBASIC syntax challenge games

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

Re: FreeBASIC syntax challenge games

Post by fxm »

@dafhi,
Have you decoded the dodicat's proposal (viewtopic.php?p=236283#p236283)?
Maybe you do not block together on the same problem (he found one of the two expected simple instructions, and not the most obvious in my opinion).
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: FreeBASIC syntax challenge games

Post by dafhi »

I thought of 2 ways

c++ style
instruction_1 = Print ... This.i++ .. :D

the other would use function pointer which I am unfamiliar with. As far as dodicat's idea, i am clueless
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBASIC syntax challenge games

Post by dodicat »

Hi dafhi.
Here is mine so far.

Code: Select all

#define instruction_1 var t=cast(parent,this):t.method
#define instruction_2  cast(child ptr,@t)->method

Type Parent Extends Object
  Declare virtual Sub method ()
  Dim As Integer I = 1
End Type
Sub Parent.method ()
  Print "Calling #" & This.I & " Parent.method()"
  This.I += 1
End Sub

Type Child Extends Parent
  Declare Sub method ()
End Type
Sub Child.method ()
  If This.I <= 7 Then
      
     
   instruction_1

    instruction_2


  End If
End Sub

Dim As Child c
Dim As Parent Ptr pc = @c
pc->method()

Sleep
 
instruction_1 is ugly, but I can't get a temporary parent to increment it's i
e.g.
(parent).method
finds the correct sub, but .i stays at 1
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

I prefer your previous proposal, although longer (one more instruction), :

Code: Select all

#define instruction_1 var t=cast(parent,this):t.method
#define instruction_2 this.i+=1:this.method
because at least one of your instructions is one of the 2 very simple instructions of my solution:
fxm wrote:Your proposal is really on the right way, but you can more simplify it:
- Try not to create a new object at each iteration.
- This will reduce instruction_1 and even instruction_2 (no longer need to increment 'I' also here).
Last edited by fxm on Sep 24, 2017 9:19, edited 1 time in total.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: FreeBASIC syntax challenge games

Post by dafhi »

okay here's mine.

Code: Select all

#define instruction_1  Print "Calling #" & This.I & " Parent.method()"
#define instruction_2  i+=1: method
:P
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: FreeBASIC syntax challenge games

Post by grindstone »

It's quite simple, once you got it:

Code: Select all

#Define instruction_1 base.method
#Define instruction_2 this.method
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Perfect!

Explanation from the first proposal of dodicat:

The first Dodicat proposal is equivalent to:

Code: Select all

#define instruction_1 Var t = Cast(Parent, This) : t.method() : This.i += 1
#define instruction_2 This.method()
OK for instruction_2 ('This.method()') that allows to re-call the 'Child.method ()' as long as 'This.I <= 7'.
So:

Code: Select all

Sub Child.method ()
  If This.I <= 7 Then
    instruction_1
    instruction_2
  End If
End Sub
is functionally equivalent to (recursion replaced by a loop):

Code: Select all

Sub Child.method ()
  While This.I <= 7
    instruction_1
  Wend
End Sub
After that, to simplify the remaining code line ('instruction_1'), the question asked is:
How to simply call the 'Parent.method ()' (from the 'Child.method ()' body), knowing that 'Child.method ()' overrides 'Parent.method ()'?

Dodicat chose to create a Parent instance in order to avoid the dynamic binding to 'Child.method ()', but as it is a new instance, its own field 'I' is different of the one tested by the caller.

A syntax as 'Cast(Parent, This).method()' does not work because the real type of 'Cast(Parent, This)' is always Child and consequently the dynamic binding is always activated (because works on the real type and not on the compile-type).
But a special FreeBASIC keyword exists to call (from a member procedure) the base method (on the hidden instance), and never the overriding method, even on a Child instance (the compiler forcing a static binding when calling the virtual method).

Use this keyword, and so you will can simplify 'instruction_1', because then working always with the same initial instance (one single field 'I'), so that the macro 'instruction_1' may contain only this one instruction.

This keyword is "BASE (Member Access)":
.....
For virtual methods, base.method() always calls the base method and never the overriding method.
.....
Last edited by fxm on Sep 24, 2017 22:25, edited 1 time in total.
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: FreeBASIC syntax challenge games

Post by grindstone »

Additional to that, if you have a grandchild class you can access the parent class with

Code: Select all

Base.Base.method
and so on.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Enigma #24, force 2
Simulation of the 'Base (Member Access)' functionality on a virtual member procedure, but applying it from outside any member procedure.

- Presently, the 'Base (Member Access)' functionality works only from inside a non static member procedure ('Base.child_instance.procedure()' is not allowed).
- 'Cast(Parent, child_instance).procedure()' allows to access the Parent procedure on a Child instance, but only if this Parent procedure is not overridden by a Child procedure.

Insert one fairly simple code line (one single instruction not hacking vptr/vtable) in the dedicated zone of below program, so that to call the 'Base.dec()' virtual procedure and to update the 'ip' field, so to obtain the following program output (check the last line):

Code: Select all

 0             0

 0             4
 4             4

 4             3
 3             3
Program where add one instruction in the dedicated zone (the solution into one only instruction is possible because of this particular type of procedure, otherwise the same method should request several instructions):

Code: Select all

Type Parent Extends Object
  Public:
    Declare Property ip () As Integer
    Declare Function inc () Byref As Parent
    Declare Virtual Function dec () Byref As Parent
  Private:
    Dim As Integer _ip
End Type
Property Parent.ip () As Integer
  Return This._ip
End Property
Function Parent.inc () Byref As Parent
  This._ip += 4
  Return This
End Function
Function Parent.dec () Byref As Parent
  This._ip -= 1
  Return This
End Function

Type Child Extends Parent
  Public:
    Declare Property ic () As Integer
    Declare Function inc () Byref As Child
    Declare Virtual Function dec () Byref As Child
  Private:
    Dim As Integer _ic
End Type
Property Child.ic () As Integer
  Return This._ic
End Property
Function Child.inc () Byref As Child
  This._ic += 4
  Return This
End Function
Function Child.dec () Byref As Child
  This._ic -= 1
  Return This
End Function

Dim As Child c
Print c.ip, c.ic

Print

c.inc()
Print c.ip, c.ic
Cast(Parent, c).inc()
Print c.ip, c.ic

Print

c.dec()
Print c.ip, c.ic
'------------------------------------ zone beginning for insertion of one line -------------------------------------
'Cast(Parent, c).dec()   '' does not allow to access 'Parent.dec()' but still 'Child.dec()'
'Cast(Function(Byref As Parent) Byref As Parent, Cptr(Any Ptr Ptr Ptr, @Parent())[0][0])(c)   '' hacking vptr/vtable

'-------------------------------------- zone ending for insertion of one line --------------------------------------
Print c.ip, c.ic

Sleep
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBASIC syntax challenge games

Post by dodicat »

Overwrite the private section of type parent?

cast(any ptr ptr,@parent)[3]=3

but obviously a poor solution.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

Not only you hack the allocated memory, but you use the fact that the 'Parent()' temporary instance is contiguous to the 'c' instance!
This true when using 'gas' but not when using 'gcc'.
A less bad solution should be:
cast(any ptr ptr,@c)[1]=3
or:
cast(integer ptr,cast(any ptr,@c))[1]=3
to get no warning.

My solution does not hack the memory, but uses the 'dec()' member function, the 'c' instance, and .....?
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

fxm wrote:Enigma #24, force 2

..... the solution into one only instruction is possible because of this particular type of procedure, otherwise the same method should request several instructions.....
The general solution, to simulate on a derived-instance a call to an overridden base-procedure (without calling the overriding child-procedure), consists on 3 instructions:
- copy-constuction of a base-instance from the derived-instance to be processed,
- call of the overridden base-procedure on the base-instance created previously,
- assignment of the resulting base-instance fields to the base-fields of the derived-instance to be processed.

If the overridden base-procedure is in particular a function returning a reference to the instance on which it was called, these 3 instructions can be compacted to 1 instruction only.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

fxm wrote:
fxm wrote:Enigma #24, force 2

..... the solution into one only instruction is possible because of this particular type of procedure, otherwise the same method should request several instructions.....
The general solution, to simulate on a derived-instance a call to an overridden base-procedure (without calling the overriding child-procedure), consists on 3 instructions:
- copy-constuction of a base-instance from the derived-instance to be processed,
- call of the overridden base-procedure on the base-instance created previously,
- assignment of the resulting base-instance fields to the base-fields of the derived-instance to be processed.

If the overridden base-procedure is in particular a function returning a reference to the instance on which it was called, these 3 instructions can be compacted to 1 instruction only.
Pseudo-code for the general solution:
  • Dim As Base_Type base_instance = derived_instance
    base_instance.overridden_procedure()
    Cast(Base_Type, derived_instance) = base_instance
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC syntax challenge games

Post by fxm »

fxm wrote:
fxm wrote:
fxm wrote:Enigma #24, force 2

..... the solution into one only instruction is possible because of this particular type of procedure, otherwise the same method should request several instructions.....
The general solution, to simulate on a derived-instance a call to an overridden base-procedure (without calling the overriding child-procedure), consists on 3 instructions:
- copy-constuction of a base-instance from the derived-instance to be processed,
- call of the overridden base-procedure on the base-instance created previously,
- assignment of the resulting base-instance fields to the base-fields of the derived-instance to be processed.

If the overridden base-procedure is in particular a function returning a reference to the instance on which it was called, these 3 instructions can be compacted to 1 instruction only.
Pseudo-code for the general solution:
  • Dim As Base_Type base_instance = derived_instance
    base_instance.overridden_procedure()
    Cast(Base_Type, derived_instance) = base_instance
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()
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBASIC syntax challenge games

Post by dodicat »

I can do it in two lines:

dim as parent p=c
Cast(Parent,c)=p.dec
Post Reply