Free Web Hosting by Netfirms
Web Hosting by Netfirms | Free Domain Names by Netfirms

Operator Descriptions
Divider

This section describes the built-in (non-overloaded) behaviour of each of the QDL operators.

Parenthesis ( ( x ) )

Parenthesis are used to ensure that sub-expression x is evaluated before other parts of an expression which have a lower level of parenthesis nesting. But everyone knows what parenthesis are for, so I don't really need to explain it.

Unlike in math class, you do not alternate between the use of round and square brackets in QDL. In QDL, always use round brackets; square brackets have a different meaning.

If the expression in parenthesis evaluates to an lvalue, the result of the parenthesis operator is still an lvalue.

Dot (x . y)

The dot operator is used to access a member named y from an instance of a Class called x. If x is the name of a variable, the result of the operation is an lvalue representing the specified member of the class instance. If x is the name of a function, the result of the operation is the function, which can be called or its address taken.

Scope Resolution (x :: y)

The scope resolution operator tells the compiler in what scope to look for identifier y. x can be omitted, and if it is, it means to look at global scope. y cannot be omitted in normal expressions, but it can be omitted in the beginning of a function signature when the function does not need a name. x, if present, must identify a Class or Enum type. If the type name is being used in a normal expression, but is not valid as a normal one-token identifier, it must be separated from the rest of the expression using the Class() pseudo-function.

Here is an example (where C is a static function or variable in Class B, but B is in Class A):

A::B::C

Array element (x [ y ])

This operator tells the compiler to access a member of x, which must be an array. y specifies the subscript, which must be an integer.

If x is a multidimensional array, the result of x [ y ] is an array with one less dimension. Thus, you can add another array element operator on the end to access the next dimension.

Pseudo-function or Function Call (x ( y ))

The function-call operator invokes a function call or pseudo-function. It is differentiated from the parenthesis operator by the fact that it is immediately preceded by the name of a function or function reference.

Information about calling functions is here, and information about pseudo-functions is (later section).

Address-of (@ x) and dereference (* x)

The address-of operator takes the address of an lvalue or function. The address-of operator cannot be used on an Inline Function or a function that has been overloaded. If the type of x is a reference (i.e. ends in @), the type returned by the address-of operator has the last @ removed. In any case, the type returned has * (pointer-to) appended to the original type.

The dereference operator accesses what is pointed to by a pointer. The type of x must be one of:

Pre-increment (++ x) and pre-decrement (-- x)

These two operators increment or decrement the lvalue x, which must be of integral, floating-point, or pointer type. The return value is x. Unlike the post-versions of these operators, the increment or decrement operation is performed as soon as x is evaluated in the expression. This makes ++ x functionally equivalent to (x += 1) and -- x functionally equivalent to (x -= 1).

In case you're wondering: although pointer variables do not exist in QDL, a lvalue pointer type results from using the address-of (@) operator on a reference. So, for example, if you have an Integer @ called IR, ++@IR causes the address stored in IR to be incremented by the size of an Integer.

Post-increment (x ++) and post-decrement (x --)

These two operators increment or decrement the lvalue x, which must be of integral, floating-point, or pointer type. The return value is x. The increment or decrement operation is performed after the rest of the expression is evaluated.

Unary minus (- x), unary plus (+ x)

The unary minus returns the negated (reversed sign) version of its argument, which must be integral or floating-point. If x is an unsigned integral type, the resultant type is a signed type of the same size (a warning may be issued about this type change.) Otherwise, the resultant type is the same as the source type.

The unary plus operator returnes the absolute value of its argument, which must be of integral or floating-point type. The absolute value is x (as an rvalue) if x is positive, or -x if x is negative.

The result of either operation is always an rvalue.

Binary not (~ x), logical not (! x)

The binary not operator returns the one's complement of x, which must be of integral type. This means that each of the 1 bits are changed to 0s, and each of the 0 bits are changed to 1s.

When using the logical not operator, x must be of integral or floating-point type. If x equals 0 or 0.0, the result is 1. Otherwise, the result is 0.

The result of either operation is always an rvalue.

Multiply (x * y), divide (x / y) and modulo (x % y)

The multiply operator multiplies x by y, the divide operator divides x by y, and the modulo operator determines the remainder when x is divided by y.

x and y must be of integral or floating-point type. The promotion rules are used to determine the type of the result of each of these operations.

The results of these operations are always rvalues.

Add (x + y) and subtract (x - y)

The add operator adds x and y, and the subtract operator subtracts y from x.

If x and y are of integral and/or floating-point types, the promotion rules are used to determine the type of the result.

The only other combinations of types for which these operators have built-in support are described in the discussion of pointer arithmetic. In summary, these are: pointer + integer, pointer - integer, pointer - pointer.

The result of either operation is always an rvalue.

Bitwise and (x & y), bitwise exclusive-or (x ^ y) and bitwise-or (x | y)

All of these operators work only on integral types. The type of the result of each operation is determined by the promotion rules. x and y are both promoted to this type. Each of the bits in the return value is the result of an and, or, or exclusive-or operation that is performed on the two corresponding bits in the promoted versions of x and y. Following is a table that shows the results of these operations.

Input bits Output bit
Bit from x Bit from y And Or Xor
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

The results of these operations are always rvalues.

Logical and (x && y) and logical or (x || y)

These operators can be used on any combination of Booleans, integral types, pointers and floating-point types. x and y are converted to Boolean in order to determine the result, but the compiler must not issue a warning for doing this conversion. The result is always Boolean. The results of all possible combinations are shown in ths table:

Input values Output values
x y && ||
False False False False
False True False True
True False False True
True True True True

The result of either operation is always an rvalue.

Ternary (x ? y : z)

The ternary operator is like a miniature If-Then-Else for expressions. x must be Boolean, or a value that can be converted to Boolean. If x is of integral, pointer or floating-point type, the compiler must not issue a warning for doing this conversion. If the result is True, y is evaluated and returned; otherwise, z is evaluated and returned. The types of y and z must match; if they do not, the promotion rules are applied to y and z to make them match. If the promotion rules do not apply to the type of y or z, a compile-time error is issued.

Here is an example of the ternary operator being used to convert a character C to uppercase:

C = ((C >= 'a' && C <= 'z') ? (C += 'A' - 'a') : C);
	// Note: the parenthesis are to make the meaning more obvious;
	// due to the precedence rules, they are not required.

The result of the ternary operator is an lvalue only if both y and z are lvalues.

Assignment (x = y)

This operator assigns the value of y to x, which must be an lvalue. The result of the operation is the lvalue y.

You can assign several variables the same value using a statement such as this:

X = Y = Z = 0;

Compound assignment

The compound assignment operators are: x *= y, x /= y, x %= y, x <<= y, x >>= y, x += y, x -= y, x &= y, x ^= y, x |= y.

Assume x #= y represents the compound assignment syntax, #= represents the compound assignment operator, and X represents the fully evaluated version of x.

The compound assignment operators combine an assignment and another operation into one operator. The effect of each compound assignment operator is that the operation denoted by # is performed on X, and the result of that operation is assigned to X. In other words, (x #= y) means (X = X # y).

Example:

X: Integer(5);
X *= 3; // Result is the same as X = X * 3, i.e. 15

It is important to understand, however, that X is evaluated only once.  Furthermore, compound assignment capability does not work automatically for user-defined classes.  For example, overloading the + operator will not automatically make the += operator work too.

Comma (x, y)

The comma operator evaluates both x and y, and returns y. Neither x nor y need to have a type.

The comma operator is used to stuff together two operations that, as far as the compiler is concerned, are unrelated. Its most common use is in the first and/or third sections of the For statements; for example, you might maintain two counters in your For statement, like this:

For X = 0, Y = 1; X < 10; X++, Y++ Do // ...

Of course, you could also use it in a standalone statement such as:

X = 10, Y = 20; // Equivalent to X = 10; Y = 20;
Table of Contents Qwertie's Site/Mirror
Next
Previous