|
Phantasmal Site > DGD > Untitled document (index.base.html) > (untitled)
Scope is a term defining where a function or variable
declaration is valid. Since programs are read top down (just like
you read this page), declarations of functions and variables are
available to the below the actual declaration. However, the scope
might be further limited.
A variable that is declared inside a function is only valid
until the end of that function (the terminating } ) is
reached. If it's declared in a block inside that function, such as
inside a for loop, it's only valid until the end of
that block (the } matching the beginning
{ of that block).
<top of file>
int GlobCount;
/* Only GlobCount is available here */
void
var_func(int arg)
{
int var_1;
/* GlobCount, arg and var_1 are available here */
< code >
{
string var_2;
/* GlobCount, arg, var_1 and var_2 are available in this block */
< code >
}
/* GlobCount, arg and var_1 are available here */
< code >
{
int var_2;
mapping var_3;
/* GlobCount, arg, var_1, var_2 and var_3 are available here
Note that this var_2 is a NEW var_2, an int not a string */
< code >
}
/* GlobCount, arg and var_1 are available here */
< code >
}
/* Here only GlobCount and the function var_func are available */
Function declarations follow the same rule of scope, though you
can't declare a function inside another function. Suppose you have
these two functions where the first uses the second:
int
func_1()
{
< code >
func_2("test");
}
void
func_2(string data)
{
< code >
}
Then you have a problem, because the first function tries to use
the second function before it is declared. This may result in an
error message, and it's bad practice in any case. To take care of
this you can rearrange the functions so that func_2
comes before func_1 in the listing. This isn't always
the best layout, and it isn't always possible. It's usually better
to write a function prototype. The function prototype should
be placed at the top of the file after the inherit and
#include statements (described later) but
before any code. It should look very much like the function
declaration itself. In this case:
< top of file, inherit and #include statements >
void func_2(string data);
< the actual code >
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.
- (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.
- 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 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
- 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.
- 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.
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. */
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) .
|