ucDefineOperator
See Also: ucDefine, ucDefineFunction, ucArg, ucArgCount, ucArgHandle, ucReturn
Defines an operator.
ucDefineOperator(Definition [, FunctionAddress
[, tHandle]])
Many of the details for defining an operator are very closely related to the details for defining a function (native vs non-native callbacks, data types, ByVal, ByExpr, etc). The ucDefineFunction topic covers those details. The operand in an operator definition is related to an parameter in a function definition. They both can be passed ByRef, ByVal, ByExpr, or ByHandle, and can be assigned a data type. Although operands on the left side of ":=", in a self-contained definition, are enclosed within curly braces, on the right side they are bare, just like the parameters are on the right side of "=" in a function definition. This topic here focuses mainly on the unique aspects of defining operators.
The Definition part can take one of the following three forms, depending on whether the operator you are defining is Prefix, Postfix, or Infix (binary):
[Precedence] Operator {Operand} [ := DefinitionCode ]
[Precedence] {Operand} Operator [ := DefinitionCode ]
[Precedence] {LeftOperand} Operator {RightOperand} } [ := DefinitionCode ]
Definition parts
Precedence
Optional. Though optional, it is highly recommended that all operator definitions include a specified precedence level. If none is supplied, then a default precedence value is used. Precedence is an arbitrary positive integer value less than 2^31, which derives its meaning by whether this value is greater than, less than, or equal to the precedence levels of other given operators. Although this value can be a literal number, it is best to use the Precedence() function when possible, since the literal numeric values for precedence levels of built-in operators is subject to change from one version to the next, whereas the levels relative to each other is not. This function returns the precedence level of another operator that’s already defined. For instance, use Precedence(“*”) instead of 60.
Operator
Required. Unlike function names which can only be alphanumeric, operator names can also consist of symbols, such as +, -, **, etc. An operator name can be alpha numeric, or non-alphanumeric, but not a combination of both.
Operand, or LeftOperand, RightOperand
Required. Operands are defined the same way as function parameters, in terms of using directives like ByRef, ByVal, and specified data types. Optional arguments or indefinite number of arguments do not apply in this context.
DefinitionCode
Optional. If the definition is not a callback, then you can supply a self-contained definition. It is important to note that unlike function definitions which use the equal sign, "=", operator definitions use a colon followed by an equal sign, ":=". This allows the equal sign by itself to be defined as an operator. Nothing is hard-coded. So should you need to define ":=" itself as an operator, you can modify the include file and change ":=" to something else.
Remarks
Example 1: Miscellaneous self-contained operator definitions
This example demonstrates several variations of self-contained operator definitions: an operator with an alphanumeric name (ShiftLeft), operators named using symbols (%, and !), and prefix, postfix, and infix versions of an operator (the ! symbol). The numeric values at the beginning of each definition represent precedence levels. For instance, ShiftLeft is defined with a precedence level of 20, while the % operator has a precedence level of 50.
Visual Basic
' This example demonstrates various self-contained
operator definitions ucDefineOperator "20 {x} ShiftLeft
{y} := x * 2^y" ' Infix ucDefineOperator "50 {x}% := x
/ 100" ' Postfix ucDefineOperator "60 !{x} := x
- 1" ' Prefix ucDefineOperator "30 {x}! := x
* 2" ' This one hides the pre-defined factorial op ucDefineOperator "10 {x} ! {y} := x * y" Print ucEvalStr("2 ShiftLeft 3")
' returns 16 Print ucEvalStr("25%") ' returns 0.25 Print ucEvalStr("!5") ' returns 4 Print ucEvalStr("!5!") ' (!5)! returns 8 Print ucEvalStr("!5!4") ' (!5) ! 4 returns 16 ' Here the precedence levels are switched ucDefineOperator "30 !{x} := x
- 1" ucDefineOperator "60 {x}! := x
* 2" ucDefineOperator "50 {x} ! {y} := x * y" Print ucEvalStr("2 ShiftLeft 3")
' returns 16 Print ucEvalStr("25%") ' returns 0.25 Print ucEvalStr("!5") ' returns 4 Print ucEvalStr("!5!") ' !(5!) returns 9 Print ucEvalStr("!5!4") ' !(5 ! 4) returns 19 |
Example 2: Non-native operator callback definition
This example uses the same callback routine as the one found in Example C2 of the ucDefineFunction topic. There, in addition to VB code, you will find source code for the other supported compilers as well. The difference here is that the definition attached to the StringRepeat callback is an operator instead of a function. It is designed to repeat a string a given number of times. In the other example, StringRepeat("Ha ", 3) would return "Ha Ha Ha ", whereas here, the * operator is defined with string as the left operand, and a number as the right operand, so that "Ha " * 3 would return "Ha Ha Ha ". This example uses a non-native callback. Native callbacks, like the one in example 3, are faster, and also easier to implement, especially when strings are involved.
Visual Basic
' The following line can be placed in Form_Load() ' Notice here that uCalc's
WideString is what matches VB's String ucDefineOperator
"Precedence("*") {ByRef MyString As WideString} * {ByVal Count As Long} As WideString",
AddressOf StringRepeat ' The following callback routine goes in a separate module, such as DemoVB.Bas Function StringRepeat(ByRef MyString As String, ByVal Count As Long) As String Dim x As
Long, TotalString As String For x = 1
To Count TotalString = TotalString + MyString Next StringRepeat = TotalString End Function |
Example 3: Native operator callback definition
This definition does the same thing as the previous example, except it is implemented using a native callback. More details can be found in the Native Callbacks section of the ucDefineFunction topic. Native callbacks are generally much faster than non-native callbacks. They are also less tricky to implement when strings are involved.
Visual Basic
' The following line can be placed in Form_Load() ucDefineOperator "Native:
Precedence("*") {MyString As
String} * {Count} As String", AddressOf Native_StringRepeat ' The following callback routine goes in a separate module, such as DemoVB.Bas Sub Native_StringRepeat(ByVal Expr As Long) Dim x As
Long, TotalString As String For x = 1
To ucArg(Expr, 2) TotalString = TotalString + ucArgStr(Expr, 1) Next ucReturnStr Expr, TotalString End Sub |
New or enhanced in version 3.0
· An operator can be overwritten in such a way that other functions or operators that use it are affected by the new definition.
· Operators can now be defined with right to left associativity.
Note:
· ucParam and ucParamStr were renamed ucArg and ucArgStr in version 3.0. However, ucParam and ucParamStr are preserved for backward compatability.
· In version 2.96, the keyword Native: was not required for some compilers when defining native callbacks. Now it’s required equally by all compilers.
New or enhanced in version 2.96
New or enhanced in version 2.9+
Issues for users migrating from version 2.0