[Next] [Up] [Previous] [Contents] [Index]
Next: 4. Flow Control Up: NannyMUD LPC Previous: 2. Fundamentals

Subsections


3. Types, operators and expressions


3.1 Identifier Names

Valid identifier names are formed from a combination of the characters a-z, A-Z, underscore, and the numbers 0-9. They must start with a letter, or underscore. Case is significant, 'x' and 'X' are two different variable names. The keywords of the LPC cannot, naturally, be used as variable names. A list of such reserved keywords can be found in appendix A.


3.2 Type Checking

Global variables that are explicitly initialised when declared are typechecked at load-time. Apart from that, there is normally no global typechecking done in LPC, neither at load-time, nor at run-time. There are, however, two #pragmas that can be declared to get global type-checking at load-time: #pragma strict_types and #pragma save_types.

The first turns on typechecking at load-time, while the latter saves the type information so it can be used by inheriting objects. Unless those are used, the types given in the source code file is just a kind of documentation.

Local type-checking can be forced by declaring the types of functions; this is covered in section 5.


3.3 Data Types and Modifiers

All variables are initialised to zero (0). Variables, functions and expressions in LPC can have one of the types int, status, float (but see below), string, object, mapping, and mixed. There is one extra type available for functions, void. That, and type-checking rules for functions, are covered in section 5.

It should perhaps be emphasised that LPC does not, despite the existence of the type 'float', use floating point numbers. The various data types somewhat more in detail:

It is also possible to have arrays of variables of any type. Arrays and mappings are treated in the section 6. Several modifiers can be applied to the variables: static, private, public, and nomask.


3.4 Constants

An integer constant like 4711, is an integer. Likewise is -12, 'c' (with the value 99), '\077', and 0xff (hexadecimal representation of 255). Integer constants overflowing the range are set to the max range. The type status behaves exactly the same way, since it is in really an integer.

String constants are a set of characters surrounded by double quotes, ". Examples of string constants are "hello world!", "\077", and "\\ \" a\n".


3.5 Declarations

All variables must be declared before they are used. A declaration contains a type, followed by a comma-separated list of variable names. For example,

  int i, j, k, l;
  int a;
declares the variables a, i, j, k, and l, as being integers.

Global variables (i.e. the variables declared outside any function) can be declared in any place, as long as the declaration precedes their first use. Global variables can also be initialised when declared (and are then type-checked):

  string tmp_s = "foo faa fuu";
declares a string variable tmp_s, and initialises it to have the value "foo faa fuu".


3.6 Arithmetic Operators

There are several arithmetic operators available in LPC: +, -, *, / and %.


3.7 Relational and Logical Operators

The relational operators are >, >=, <=, <, == and != .


3.8 Increment and Decrement Operators

The increment, ++, and decrement, -, operators works on variables with type integer.


3.9 Bitwise Operators

There bitwise operators are |, ^ , &, << and >>.


3.10 Assignment Operators and Expressions

The assignment of a value to a variable is usually done through the construction var = expr. The value of 'expr' is assigned to the variable 'var'. The value of the whole is the new value of the variable 'var'.

The expression

  i = i + 4;
can be written in a shorter form:
  i += 4;
where the operator += is known as an assignment operator. There are several assignments operators available in LPC: +=, -=, *=, /=, %=, &=, ^ =, |=, <<= and >>=.

If 'expr1' and 'expr2' are expressions, and 'op' one of the above operators,

  expr1 op= expr2;
is equivalent to
  expr1 = (expr1) op (expr2);
but 'expr1' is evaluated only once.


3.11 Other Operators

There are a few operators available that do not fit into any of the above categories.


3.12 Conditional Expressions

The statements

  if (expr1)
    expr2;
  else
    expr3;
can be written as an expression using the ternary operator :? : expr1 ? expr2 : expr3. This is truly an expression and can thus be used wherever an expression can be used. It makes for stream-lined code, but can also reduce the readability of your code drastically.


3.13 Precedence and Order of Evaluation

Here is the list of operators in LPC, listed in descending precedence, from left to right and top to bottom (i.e. :: has higher precedence than ->, and [] has higher precedence than -).

:: -> []
-- (post-decrement) ++ (post-increment) ~
! - (unary minus) -- (pre-decrement)
++ (pre-increment) (type) (type cast) /
% * -
+ >> <<
<= < >=
> != ==
& ^ |
&& || ?:
/= %= *=
>>= <<= ^ =
|= &= -=
+= = ,
..    
     

The order of evaluation of expressions are basically from left to right. The precedence of operators can of course change this. Unlike many other programming languages, LPC has the property that in the case of two expressions having the same precedence, they are evaluated left to right.

Thus, for example, there is no ambiguity of what the value is of the subscript in

  a[i] = i++;
as it will always be the old value.


3.14 The time cost of everything

The MUD process is single-threaded. In order to prevent any piece of LPC-code to be able to hang the MUD, every operation performed when interpreting the code has been associated with a cost, called 'nodes'. The sum of evaluated nodes is not allowed to pass a certain limit, determined when the driver is compiled, known as 'max eval cost'. It is good to know the limit is there; the exact value is not that important.

Basically, the association of the cost with the operation is arbitrary in that it is not based on real life time; rather it is based on the driver hackers (sourcerers) whims.



Footnotes

... efuns1
See section 5.1
..._object()2
'save_object()' is a function provided by the driver to dump a representation of an objects variable and their values to file.
..._object()3
'restore_object()' reads an objects variables and values from file.
...call_other4
'call_other' is a function provided by the driver to call functions in a specified object. The specified object can, naturally, be the calling object itself. That might seem a waste, but consider 'shadows' (see 8.1).
... expr25
Strictly speaking, it is the value of expression1, etc., that is used. Pointing this out every time makes the text rather cumbersome, so we adopt the slightly sloppy habit of letting this be understood by the context.
... efun6
See section 5.1.
..._other()'7
In fact, it is exactly the same thing, written in two different ways.

[Next] [Up] [Previous] [Contents] [Index]
Next: 4. Flow Control Up: NannyMUD LPC Previous: 2. Fundamentals
Mats Henrik Carlberg
1998-03-25