... Operator

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
FlatEarth

... Operator

Post by FlatEarth »

One of my dreams:
the ... operator is useful and with a little change if needed, it can increase pb syntax power.
you can see how this operator works in the following codes.

Code: Select all

Procedure max(...)
  Protected Dim var_args(...)
  Protected mx = var_args(0)
  For i=0 To ArraySize(var_args())
    If (var_args(i) > mx) : mx = var_args(i) : EndIf
  Next
  ProcedureReturn mx
EndProcedure

Debug max(22,133,45)                  ; result --> 133
Debug max(90,88,12,45,677,211)        ; result --> 677
Debug max(33,25,233,85,11,231,34,64)  ; result --> 233
Of course, I know that we can implement the (Max) algorithm in different ways.
Olli
Addict
Addict
Posts: 1200
Joined: Wed May 27, 2020 12:26 pm

Re: ... Operator

Post by Olli »

; '___' instead of '...'

; array name is Arg()
; be careful to ArgCount which has been defined as a local integer

; -9223372036854775808 for X64
; 2147483648 for X86
; this is a reserved argument value

; only for integers and pointors
; 16 arguments maximum

Code: Select all

;*************************************************************************************
#None = 1 << 63

Macro Ar_
 Argument# MacroExpandedCount = #None
EndMacro

Macro ___
 Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_, Ar_
 For ArgCount = 0 To 15
  If PeekI(@Argument1 + ArgCount * SizeOf(Integer) ) = #None
   Break
  EndIf
 Next
 Dim Arg.I(ArgCount)
 Arg(0) = ArgCount
 For ArgCount = 1 To Arg(0)
  Arg(ArgCount) = PeekI(@Argument1 + (ArgCount - 1) * SizeOf(Integer) )
 Next
 ArgCount ! (0
EndMacro


;- Syntax example



Procedure Test(___)
 For I = 1 To Arg(0)
  Debug Arg(I)
 Next
EndProcedure

Test(1,2,5,10,20)
User avatar
Derren
Enthusiast
Enthusiast
Posts: 316
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: ... Operator

Post by Derren »

I have never seen a "..." operator used in such a way.
I think it's confusing. In other languages "..." can be used to ommitt redundant data, for example if you want the 1st, 4th, 5th, 6th, 7th and 11th element, you can write something like "1, 4...7, 11"

Implicit Array creation and population would be more verstatile and can achieve the same.

Code: Select all

Procedure Max( Array args(1) )
 For i = 0 to ArraySize(args())-1
   ;..
 Next
EndProcedure

Debug Max( [1, 2, 5, 12])
As much as I love PB, this kind of ineffienct code is what annoys me beyond belief.

Code: Select all

arr(0) = 1
arr(1) = 2
arr(3) = 9
Olli
Addict
Addict
Posts: 1200
Joined: Wed May 27, 2020 12:26 pm

Re: ... Operator

Post by Olli »

Added to trick and tips

Code: Select all

arr(0) = 1
arr(1) = 2
arr(3) = 9
I did not understand the link but we could find this :

Code: Select all

For i = 0 To 2
   j = 1 << i - 1
   k = 1 << j + Bool(j & 2)
Next
For the rest of you request, it seems that mk-soft made something for trick and tips (just no nested in a arguments set, but from directly to arrays).
Rinzwind
Enthusiast
Enthusiast
Posts: 679
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: ... Operator

Post by Rinzwind »

Yes inline array initialization is a must have and severely missing from pb. Some api’s depend on null terminated string arrays which are a pain to pass with pb. Some c code looks so ugly and lengthy when converted to pb because of this. What about array lookup tables defined in source? Also helps with procedures indeed because we dont have varargs too.
Olli
Addict
Addict
Posts: 1200
Joined: Wed May 27, 2020 12:26 pm

Re: ... Operator

Post by Olli »

Rinzwind wrote:What about array lookup tables defined in source?
Did you try this ?
Strings table
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: ... Operator

Post by mk-soft »

PB copy the parameter to the stack in right order.

Code: Select all

;-TOP

#None = 1 << (SizeOf(integer) -1)

; Max 8 parameters
Macro iArgs
 Arg1=#None,Arg2=#None,Arg3=#None,Arg4=#None,Arg5=#None,Arg6=#None,Arg7=#None,Arg8=#None, ArgEnd=#None
EndMacro

;- Syntax example
Procedure Sum(iArgs)
  Protected *arg.integer = @Arg1 ; Get pointer to the first parameter
  Protected r1
  While *arg\i <> #None
    r1 + *arg\i
    *arg + SizeOf(integer) ; Set pointer to the next parameter (Allways size of integer) 
  Wend
  ProcedureReturn r1
EndProcedure

sum = Sum(1,2,5,10,20)
Debug sum
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Olli
Addict
Addict
Posts: 1200
Joined: Wed May 27, 2020 12:26 pm

Re: ... Operator

Post by Olli »

Deutsch Qualität :P
User_Russian
Addict
Addict
Posts: 1519
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: ... Operator

Post by User_Russian »

Code: Select all

Structure ArrI
  i.i[0]
EndStructure

ProcedureC Test(Count)
  Protected *Param.ArrI=@Count+SizeOf(Count)
  Protected i
  
  PrintN("Count = "+Count)
  Print("Parameters: ")
  For i=0 To Count-1
    Print(Str(*Param\i[i])+"  ")
  Next
  
  PrintN(#CRLF$+"----")
EndProcedure
OpenConsole()
CallCFunctionFast(@Test(), 2, 1, 2)
CallCFunctionFast(@Test(), 10, 2, 8, 20, 100, 4, 1234, 10000, 10, 16, 80)
Input()
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: ... Operator

Post by Demivec »

User_Russian wrote:

Code: Select all

Structure ArrI
  i.i[0]
EndStructure

ProcedureC Test(Count)
  Protected *Param.ArrI=@Count+SizeOf(Count)
  Protected i
  
  PrintN("Count = "+Count)
  Print("Parameters: ")
  For i=0 To Count-1
    Print(Str(*Param\i[i])+"  ")
  Next
  
  PrintN(#CRLF$+"----")
EndProcedure
OpenConsole()
CallCFunctionFast(@Test(), 2, 1, 2)
CallCFunctionFast(@Test(), 10, 2, 8, 20, 100, 4, 1234, 10000, 10, 16, 80)
Input()
Nice to see some undocumented behavior (at least to my knowledge).

But try your method without any parameters.

Code: Select all

CallCFunctionFast(@Test())
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ... Operator

Post by Josh »

Demivec wrote:But try your method without any parameters.

Code: Select all

CallCFunctionFast(@Test())
If you try to understand the code from User_Russian, the two given examples result in a rule according to which a CallCFunctionFast(@Test()) is not allowed, but only a CallCFunctionFast(@Test(),0).
sorry for my bad english
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: ... Operator

Post by Demivec »

Josh wrote:
Demivec wrote:But try your method without any parameters.

Code: Select all

CallCFunctionFast(@Test())
If you try to understand the code from User_Russian, the two given examples result in a rule according to which a CallCFunctionFast(@Test()) is not allowed, but only a CallCFunctionFast(@Test(),0).
The rule is implied but is neither stated nor enforced.

The documentation for CallCFunctionFast() dictates that all other parameters after the function address are optional.

Since I was unaware that the number of parameters was passed at all I would invite the sharing of any other details as to what is being passed. Apparently the number of parameters being passed is not pushed on the stack if the number is zero. I would appreciate any additional information or reference that I can look to to dig up any other info that doesn't want to be shared here.
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ... Operator

Post by Josh »

I'm not quite sure if it is because of my lack of English skills or if it is actually possible that the rule resulting from the two examples cannot be recognized.

Yes, the rule is implicit, is not stated, but is enforced and should be recognizable at a glance. In any case, it has absolutely nothing to do with the fact that for CallFunctionFast() all parameters are optional, it has only to do with how the procedure Test() has to be called. If you look at the procedure, you will see that the first parameter is used as number of following parameters. This can also be seen in the procedure call. So it should be self-explanatory that a 0 is to be passed as a parameter for zero following parameters.

You don't have to suspect a big miracle behind every code, just read what is written there and the miracle becomes a simple code as if by a miracle.
sorry for my bad english
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: ... Operator

Post by Demivec »

Josh wrote:I'm not quite sure if it is because of my lack of English skills or if it is actually possible that the rule resulting from the two examples cannot be recognized.

Yes, the rule is implicit, is not stated, but is enforced and should be recognizable at a glance. In any case, it has absolutely nothing to do with the fact that for CallFunctionFast() all parameters are optional, it has only to do with how the procedure Test() has to be called. If you look at the procedure, you will see that the first parameter is used as number of following parameters. This can also be seen in the procedure call. So it should be self-explanatory that a 0 is to be passed as a parameter for zero following parameters.

You don't have to suspect a big miracle behind every code, just read what is written there and the miracle becomes a simple code as if by a miracle.
Thanks for your explanation. I have a high opinion of your comprehension and use of the English language and do not believe that enters into things at all here.

I tested the sample code by not passing any optional parameters to discern if a count of zero would be passed as it did with any number of other optional parameters. It did not. I am not familiar with this aspect of things when using the CallCFunctionFast() procedure or that one could take advantage of it as User_Russian did. I do understand the procedure's function and what it is trying to accomplish and that was never a part of my question.

I am still wondering about any documentation for the 'count for the optional parameters' being passed as the first parameter on the stack or not, followed by the optional parameters. Do you have any information on this or any other aspect of the CallCFunctionFast() that is not in the PureBasic Help?
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ... Operator

Post by Josh »

Demivec wrote:Do you have any information on this or any other aspect of the CallCFunctionFast() that is not in the PureBasic Help?
Don't think so complicated. User_Russian passes the number of following parameters as the first parameter when calling the procedure Test() and the procedure evaluates this again. There is no miracle behind this.

CallCFunctionFast(@Test(), 2, 1, 2)
CallCFunctionFast(@Test(), 10, 2, 8, 20, 100, 4, 1234, 10000, 10, 16, 80)
sorry for my bad english
Post Reply