Page 1 of 2

... Operator

Posted: Sun May 03, 2020 3:21 pm
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.

Re: ... Operator

Posted: Mon Jun 08, 2020 12:27 pm
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)

Re: ... Operator

Posted: Mon Jun 08, 2020 2:26 pm
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

Re: ... Operator

Posted: Mon Jun 08, 2020 3:34 pm
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).

Re: ... Operator

Posted: Tue Jun 09, 2020 1:42 am
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.

Re: ... Operator

Posted: Tue Jun 09, 2020 8:12 pm
by Olli
Rinzwind wrote:What about array lookup tables defined in source?
Did you try this ?
Strings table

Re: ... Operator

Posted: Fri Jun 12, 2020 5:32 pm
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

Re: ... Operator

Posted: Fri Jun 12, 2020 8:49 pm
by Olli
Deutsch Qualität :P

Re: ... Operator

Posted: Sun Jun 21, 2020 10:20 am
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()

Re: ... Operator

Posted: Mon Jun 22, 2020 12:44 am
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())

Re: ... Operator

Posted: Mon Jun 22, 2020 4:06 am
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).

Re: ... Operator

Posted: Mon Jun 22, 2020 4:51 am
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.

Re: ... Operator

Posted: Mon Jun 22, 2020 6:44 am
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.

Re: ... Operator

Posted: Mon Jun 22, 2020 7:24 am
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?

Re: ... Operator

Posted: Mon Jun 22, 2020 7:53 am
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)