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