|
Phantasmal Site > DGD > DGD Reference Manual > LPC > Expressions
Expressions
An expression is an instruction or set of instructions that
results in a value. A variable is an expression since it yields its
contents as a result. a + b is a valid expression,
because a and b are variables
(expressions) and + is an operator that takes two
expressions to make another expression. a = b + c; is
a full statement ending in a ; . Because the
= operator returns a value, a = b + c is
an expression, but when you add a ; , it becomes a
statement. It's like when you add a period to the end of a bunch of
words and suddenly you have a sentence.
Function calls are valid expressions. They are written simply as
the name followed by a set of parentheses with the arguments that
the functions uses listed inside. Take the simple function
max() for example, that returns the maximum of the two
floating-point arguments. To determine the maximum of
4.0 and 10.0 , you would write
max(4.0, 10.0) as the expression. The result of the
function call must be stored or used in an expression, or it is
lost. That's fine if you're calling the function because of some
other effect it has, such as write_file() .
Operator expressions
The LPC language defines a large set of operator expressions.
These are simply expressions that operate on other expressions.
What follows here is a list of them. This section uses condensed
notation to save space and reduce complexity.
- E
- Any expression, including compound expressions.
- V
- A variable.
Miscellaneous operators
- (E)
- The expression inside the parentheses is evaluated before
anything outside the parenthesis. This is useful for isolating
expressions that need to be done in a specific order. It's also
useful when you are uncertain about operator precedence, or when
you want to make it obvious to readers of your code what the
precedence is.
- E1, E2
- The first expression is
evaluated first and the result stored, then E2 is evaluated and
the result is thrown away. Finally, the stored result of E1 is
returned as the value of the entire expression. The statement
a = 1, 2, 3; will set 'a' to contain '1'.
- V = E
- The variable is given the
value of the expression. The resulting value of this entire
expression is also the value of E. For instance,
a = b =
4; will set a and b to be 4. It can also be written
a = (b = 4) to illustrate the order of
execution.
Arithmetic operators
- E1 + E2
-
The expressions are evaluated and the results added to each
other. You can add integers, floats, strings, arrays and
mappings. Strings, arrays and mappings are simply concatenated
- pasted together to the end of the first argument.
It's also possible to add integers to strings, they will
then be converted to strings and pasted to the end of the
string.
- E1 - E2
-
E2 is subtracted from E1. You can subtract integers, floats
and any type from arrays of the same type. For arrays the item,
if it exists in the array it is subtracted from, is removed
from the array. If it doesn't exist in the array, the array is
returned intact.
- E1 * E2
- E1 is multiplied by E2. This only works on integers and
floats.
- E1 / E2
- E1 is divided by E2. This only works on integers and floats.
- E1 % E2
- The remainder (also called the modulus) of the expression 'E1 /
E2' is returned. This only works with integers. For instance,
14
% 3 will yield 2 as the remainder.
- -E
- Return E, negated arithmetically. This only works on integers
and floats. For either one, the value returned is equal to zero
minus E, or negative E.
- E++, ++E
-
The expression E is incremented by one. If the operator is
in front of the expression (called "prefix") then the
incremented value is returned, otherwise the previous value is.
For instance, if the variable ctr is equal to 3
then ++ctr would return 4 and ctr++
would return 3. This only works on integers.
The value of ++a is also an lvalue, which means
it can be assigned to. If you don't immediately know what that
means, don't do that.
'a = 3; b = ++a;' will yield the result 'a = 4, b = 4', while
'a = 3; b = a++;' will yield the result 'a = 4, b = 3'.
- E--, --E
-
The expression 'E' is decremented by one. If the operator is in
front of the expression, the decrement is done before the value is
returned, otherwise afterwards. This only works on integers.
'a = 3; b = --a;' will yield the result 'a = 2, b = 2', while
'a = 3; b = a--;' will yield the result 'a = 2, b = 3'.
Boolean operators
Boolean operators are applicable only to integers with the
exception of the & and | operators,
which also work on arrays. Internally an integer is 32 bits long.
However, in the following examples I will only show the ten last
bits as the others are 0 and can be ignored with the one exception
of the ~ -operator.
- E1 & E2
-
E1 and E2. Every bit which is
set in both E1 and E2 will also be set in the result. Any bit
which is zero in either one will be zero in the result.
1011101001 (= 745)
1000100010 & (= 546)
------------
1000100000 (= 544) => 745 & 546 = 544
Used on two arrays, this function will return a new array
that holds all elements that are members of both of the argument
arrays. Thus, it performs a kind of set-intersection on the arrays.
- E1 | E2
-
E1 or E2. Every bit which is
set in either E1 or E2 will be set in the result. Any bit which
is zero in both E1 and E2 will be zero in the result.
1011101001 (= 745)
1000100010 | (= 546)
------------
1011101011 (= 747) => 745 | 546 = 747
Used on two arrays, this function will return an array
containing any element which is in either one of the original two
arrays. If E1 and E2 share no members in common, this is the same
as E1 + E2.
- E1 ^ E2
-
E1 xor (exclusive or) E2. A bit
which is zero in both or one in both is zero in the result. A
bit which is set in either E1 or E2, but not both, is one in
the result.
1011101001 (= 745)
1000100010 ^ (= 546)
------------
0011001011 (= 203) => 745 ^ 546 = 203
- ~E
-
1-complement of E (invert E).
This is a unary operator, meaning it takes only one argument. A
bit which is one in the argument will be zero in the result and
vice-versa.
00000000000000000000001011101001 ~ (= 745)
----------------------------------
11111111111111111111110100010110 (= -746) => ~745 = -746
The above example might be hard to understand unless you
really know your binary arithmetic. However, trust me when I say
that this is not a typo, it's the way it should look. ~745
is different from -745 -- one is a one's complement and the other
is a two's complement. Read about twos-complement binary arithmetic
and all will be made clear.
- E1 << E2
-
E1 is shifted left E2 steps.
This multiplies the value of E1 by two to the power of E2. For
instance, if E2 was three,
E1 << E2 would be
E1 * 8 .
5 << 4 => 101(b) << 4 = 1010000(b) = 80
- E1 >> E2
-
E1 is shifted right E2 steps.
This divides the value of E1 by two to the power of E2, rounded
down. For instance, if E2 was five,
E1 >> E2
would be equal to E1 / 32 .
1054 >> 5 => 10000011110(b) >> 5 = 100000(b) = 32
Conditional (logical) operators
- E1 || E2
- Returns true if E1 or E2
evaluates as true. Will not evaluate E2 if E1 is true. The fact
that it won't evaluate the second argument if the first is true
is called "short circuit evaluation".
- E1 && E2
- Returns true if both E1 and
E2 evaluates as true. Will not evaluate E2 if E1 is false. The
fact that it won't evaluate the second argument if the first is
false is called "short circuit evaluation".
- !E
- Returns true if E is false and vice versa.
Comparative operators
- E1 == E2
- Returns true if E1 is equal
to E2. This operator can be used on all types, but see the
special section later on arrays and mappings. Equality works
differently on them than you might think.
- E1 != E2
- Returns true if E1 isn't
equal to E2. This operator can be used on all kinds of types, but
see the special section later on arrays and mappings. It works
differently on them than you might think.
- E1 > E2
- Returns true if E1 is greater
than E2. This operator can be used on all types except arrays and
mappings.
- E1 < E2
- Returns true if E1 is less
than E2. Can be used on all types except arrays and
mappings.
- E1 >= E2
- Returns true if E1 is greater
or equal to E2. This operator can be used on all types except
arrays and mappings.
- E1 <= E2
- Returns true if E1 is less or
equal to E2. This operator can be used on all types except arrays
and mappings.
Prefix allocation
All of the arithmetic and
boolean operator expressions can be written in a shorter way if
what you want to do is use an operator on a variable and a value
(or two variables) and then store the result in the variable.
Say that what you want to do is this a = a + 5; . A
much neater way of writing that is a += 5; . This does
exactly the same thing with less keystrokes and less chance of
error in typing. Many people also find it more readable.
You write all the others in the same way. So the result variable
comes first, then the operator directly followed by =
and then the value to operate on. Make sure not to put a space
between the operator and the equals sign, and make sure to put the
operator before the equals sign.
a >>= 5; /* a = a >> 5; */
b %= d + 4; /* b = b % (d + 4); */
c ^= 44 & q; /* c = c ^ (44 & q); */
c =+ 7; /* c = (+7), probably not what you wanted. */
c + = 7; /* Error! Don't use the extra space. */
Precedence and Order of evaluation
The table below summarizes the rules for precedence and
associativity of all operators, including those which we have not
yet discussed. Operators on the same line have the same precedence,
rows are in order of decreasing precedence, so, for example,
* , / and % all have the same
precedence, which is higher than that of + and
- .
Note that the precedence of the bitwise logical operators
& , ^ and | falls below
== and != . This implies that bit-testing
expressions like the one below must be fully parenthesized to give
proper results.
if ((x & MASK) == 0) ...
- () []
- Left to right
- ! ~ ++ -- - (type) * &
- Right to left
- * / %
- Left to right
- + -
- Left to right
- << >>
- Left to right
- < <= > >=
- Left to right
- == !=
- Left to right
- &
- Left to right
- ^
- Left to right
- |
- Left to right
- &&
- Left to right
- ||
- Left to right
- ?:
- Right to left
- = += == etc.
- Right to left
- ,
- Left to right
Note that in the list, (type) denotes a typecast.
Note also that in every case, a unary operator is higher precedence
than its binary equivalent. So the expression -7 - 5
is equal to (-7) - 5 instead of
-(7-5) .
|