Table of Contents
We have seen in the previous sections a couple of operator examples. The "="
symbol represents the assignment operator, which can be used to assign
values to variables. The dot operator (.) is used to separate methods and
properties from variable or class identifiers. In Biferno, as in many other
programming language, a large number of operators is available. Operators
belong to three main categories: arithmetic, logical and bit-wise (acting on
individual bits).
Before moving on to the description of operators let's clarify how to start a new
line in the middle of an expression. The backslash character '\' must be
used before starting the new line, as in:
<?
// the following expression is correct
a = 3 + \
5
// the following expression will generate a syntax error
a = 3 +
5
?>
In the following we will often use the backslash character within an expression. Concersely, we recall that it is legal to start a new line within a Biferno string. If we insert a backslash character in front of the new line, the effect is not to include the newline character sequence in the string itself (the newline character sequence is, depending on the platform, either CR, LF or CRLF).
Arithmetic operators implement the elementary sum, difference, multiplication, division, and modulus functions. These operations are usually performed on variables of numerical classes.
The sum operator, if applied to variables of the string class, is
equivalent to the concatenation operator. In the following example we show
how to concatenate string class variables with numerical class variables
using the + operator:
<?
n = 4 // the n variable is of the int class and has value 4
myString = "The n variable is " + n
?>
After the concatenation operation the value of the myString variable is
"The n variable is 4". This implies that a string has been automatically
derived from the integer variable n in order to perform the concatenation.
The modulus operator (%) returns the remainder of the division of two
numbers. The increment (++) and decrement (--) unary operators provide a
short way to denote the addition or the subtraction of one (the number one)
to their argument. The increment operator was introduced in the previous
chapter when we used the for flow control instruction. The i++ expression
is equivalent to i = i + 1. The increment and decrement operators can be
also used in front of a variable identifier. In this case the variable is
incremented (or decremented) before the value of the variable is returned,
which makes a difference whenever the variable is part of an expression.
Consider the following example:
<?
a = 1
b = a++ // b is 1, a is 2
c = ++a // c is 3, a is 3
?>
The second instructions assigns to b the value of a and then increments a
by 1. The third instructions increments a by 1 and then assigns the value
of a to c.
Table 7.1. Arithmetic Operators
| Operator | Operation Performed |
|---|---|
| + | Sum or concatenation |
| - | Subtraction |
| * | Multiplication |
| / | Division |
| % | Modulus |
| ++ | Increment |
| -- | Decrement |
Table 7.1, “Arithmetic Operators” lists all arithmetic operators and
their function. The first four operators in Table 7.1, “Arithmetic Operators” can be combined using the assignment
operator = to simplify code writing. E.g. we can use the shortened form a += 1 instead of a = a + 1 (the combined operators -=, *=, /= can be used
in a similar fashion).
Logical operators compare two values and return one of the two Boolean
values true or false. In Biferno, as in other programming languages, the
numerical value 0 (zero) is considered equivalent to false, while any
non-zero numerical value is considered true. Similarly, the null string
(the zero-length string represented by "") is considered false, while any
string of non-zero length is considered true.
Table 7.2 lists all logical operators and their function.
Table 7.2. Logical Operators
| Operator | Operation Performed |
|---|---|
| < | Less than |
| > | Greater than |
| <= | Less or equal than |
| >= | Greater or equal than |
| == | Is equal to |
| != | Is not equal to |
| && | And |
| || | Or |
| ! | Not |
| NOT | Not |
The XOR (exclusive or) logical operator is not predefined in Biferno.
Notice that the XOR operator can be implemented by using other logical
operators. In fact, if a and b contain Boolean values, the operation a XOR
b can be written as: !a && b || a && !b.
Readers new to computer programming languages should take note of the
difference between the assignment (=) and the equal (==) operators,
particularly in the case of the if control instruction, where it is
possible to execute an assignment operation within the conditional test. We
will discuss this in following chapters.
Bit-wise operators are different from logical operators in that they do not act on the logical value of their argument, but rather on the individual bits representing that value. A bit is a binary digit and can assume the values 1 or 0. Any numerical value can be represented in binary form as a sequence of bits.
This example uses the binary representation (also called base 2
representation) of unsigned integer numbers. To see how bit-wise operators
act, consider the expression: a = 5 & 6. The & character represents
the AND bit-wise operator. The binary representation of 5 is 0101 (or 2^2 +
2^0, i.e. 4 + 1). The binary representation of 6 is 0110. When the AND bit-
wise operator is applied to this two numbers, the AND logical operator is
applied to all corresponding bits in the binary representation of the two
numbers. The result is 0100, i.e. the number 4.
Table 7.3. Arithmetic Operators
| Operator | Operation Performed |
|---|---|
| & | Bit-Wise and |
| | | Bit-Wise or |
| >> | Shift right every bit |
| << | Shift left every bit |
Table 7.3, “Arithmetic Operators” lists all bit-wise operators and their function.
In Biferno an expression is represented by one or more identifiers or literal constants, possibly separated by operators.
Table 7.4. Arithmetic Operators
| * / % | Highest precedence |
| + - | |
| << >> | |
| < > <= >= | |
| == != | |
| & | |
| | | |
| && || | |
| = | Lowest precedence |
The value of an expression is given by the result of the operators applied
to the identifiers. The value of an expression can be null. An expression
can be situated on both sides of an assignment. When it is on the left side
(before the = operator), the result of the expression typically decides
where the result of the expression following the = operator will be
stored. Expressions are normally computed from the left to the right,
except when operator precedence rules dictate otherwise. If any other
order in the execution of operations within an expression is desired,
parentheses should be used.
When variables are used within expressions, one must take special care in the classes the variables belong to. This is important in order to correctly foresee the class of the result of the computation, to avoid errors due to the impossibility of implicitly converting values from one class to another. Notice also that some operators can be applied only to certain classes.
Table 7.4, “Arithmetic Operators” shows operator precedence rules in Biferno, sorted by precedence in descending order (from operators with higher precedence, i.e. applied first, to operators with lower precedence).
We have mentioned that in some cases the value of a variable (or constant or literal) is automatically converted from his primitive class into a new one during an assignment operation.
This automatic mechanism is called implicit type casting. Type casting is implemented by a series of internal procedure within the primitive Biferno classes, which operate a transparent on-the-fly conversion according to well-defined precedence rules (these procedures can be also applied to user-defined classes).
The primitive Biferno classes are boolean, int, unsigned, long, double, string and char.
The implicit type mechanism casting relieves the programmer, when possible, from the specification of the class a variable has to be converted into. We can write:
<?
a = 1 // a is of the int class
b = "sun" // b is of the string class
c = b + a // c is of the string class and its value is "sun1"
?>
The last line in the example above can also be written as follows using explicit type casting:
c = b + (string)a
Table 7.5. Precedence of Primitive Classes for Implicit Type Casting
| string | Highest precedence |
| double | |
| long | |
| unsigned | |
| int | |
| char | |
| boolean | Lowest precedence |
Table 7.5, “Precedence of Primitive Classes for Implicit Type Casting” lists precedence rules for Biferno implicit
classes for type casting operations. As seen from the table, the string
class has precedence on numerical classes and Booleans, and thus an
expression involving concatenation of numbers and strings always results in
a string, regardless of the ordering of terms of the expression. The
precedence rules hold for all operators except for the logical operators
&&, ||, == and !=, for which the Boolean class has highest
precedence.
Some conversions (implicit or explicit) between primitive classes are not possible. E.g. as string can be converted into a number only if it contains no characters other than numerical, separators and possibly a sign character. A char class variable, i.e. a string constituted by a single character, is converted in a number only of the corresponding character is a numerical character. This example will help understanding the mechanism:
<?
a = "20" + 1 // a is of the string class and its value is "201"
b = (int)"20" + 1 // b is of the int class and its value is 21
c = 1 + (char)"5" // c is of the int class and its value is 6
d = (int)"sun" // ERROR! (Err_IllegalTypeCast)
?>
When Booleans are implicitly converted into strings, the false value is
converted into the empty string "". Notice that the Boolean value of the
empty string is false. There are no predefined precedence rules for Biferno
non-primitive classes and user- defined classes (see Chapter 11, User classes). When using these classes, type casting must
always be performed explicitly, and care must be taken that it is possible
to convert the value of the object be type cast into the target class.