What Are Types
A type determines what kind of data can be stored and LSL supports seven distinct types:
Integer
An integer is a whole number between -2,147,483,648 and 2,147,483,647. The following are some examples of integers in use:
integer int = -23; // in the language C, integers are called int. Don't be confused by this! integer foo = 235632; integer blar = 0;
Float
This is a floating point (or decimal) number with seven significant figures that can be positive or negative. The largest positive or smallest negative number that can be represented is +/- 3.4028235E38, while the smallest positive or largest negative number that can be represented is +/- 1.17549351E-38. Examples of floats are as follows:
float e = 2.718128; // the decimal point indicates that this is a float float f = 0.f; // a trialing ".f" can also be used float one = 1; // even though the literal "1" is an integer, this assignment will work. integer i_one = 1; // note: if (one == i_one) is a BAD idea! More on this later.
String
A string is a collection of characters, such as the following:
string name = "Exposition Linden"; string character = "c"; // single characters in LSL are just string string number = "1"; // note: "1" != 1
Vector
A vector is three floats representing x, y, and z components. A vector is generally used as a position, velocity, acceleration, or color. All three values can be set simultaneously, or they can be set as individuals:
vector pos = <123.3, 54.f, 32>; // vectors will promote entries into floats vector vel; vel.x = 12.f; // this is much vel.y = 23.f; // slower than initializing via a vel.z = 36.f; // vector!!
List
Since LSL doesn't have arrays or structures, the primary method for storing collections of data is lists. All the other data types may be placed in lists (but a list can't be placed in a list). There are many different ways to work with lists; this chapter will cover some of them, and the LSL Wiki (http://lslwiki.com/lslwiki/wakka.php?wakka=list) has excellent examples. More on lists later.
Rotation
A rotation is four floats representing the x, y, z, and s components of a quaternion rotation. Although quaternions are extremely complicated and often confusing, LSL allows them to be used without your having to master the underlying theory. We'll talk more on rotations later, and you can check out http://lslwiki.com/lslwiki/wakka.php?wakka=rotation. Here are some sample rotations:
rotation rot = <0.f, 0.f, 0.f, 1.f>; // Rotations in LSL are internally normalized rotation rot = <32, 2, -9, 128>; // even if your initialization is not
Key
A UUID, or Universally Unique Identifier, is used to identify many objects within Second Life. Like rotations, keys allow you to use UUIDs without having to write a lot of code to support them. We'll go over details later, but you can also consult http://lslwiki.com/lslwiki/wakka.php?wakka=key.
// you almost never need to initialize keys with literals like this. key object_id = "00000000-0000-0000-0000-000000000000";
Typecasting is used when variables of different types are assigned to each other. LSL supports two implicit conversions: integer to float and string to key. These allow the following statements to work correctly:
float my_float = 4; // although you really should write this as 4.f // data between " and " can be either a string or a key. key object_id = "00000000-0000-0000-0000-000000000000";
For any other conversions, explicit typecasting is needed. Like C, a typecast is the type you wish to cast to inside parentheses:
integer bad_pi = (integer)3.1425926; // bad_pi == 3 float good_pi = (float)"3.1415926"; // good_pi == 3.1415926
Now let's discuss the if statements. The if statement is the simplest of the conditional, or flow control, statements in LSL. If the code within the parentheses evaluates to TRUE, then the code within the braces is executed. The if statement is only type of expression in LSL for flow control. Flow control allows you to make decisions about whether pieces of code are executed (for more detail, consult http://lslwiki.com/lslwiki/wakka.php?wakka=FlowControl). LSL's flowcontrol statements are as follows:
integer expression = TRUE; // TRUE is an integer constant in LSL. TRUE == 1 if (expression) { // do something if expression == TRUE } else { // do something else if expression == FALSE } if (expression) // do something in one line else // do something else in one line while(expression) { // do something until expression == FALSE. FALSE == 0 } do { // do something until expression == FALSE. FALSE == 0 } while(expression); integer i; // an iterator for (i = 0; i < 100; i++) { // do something 100 times, where i starts at 0 and counts up to 99 // this code will exit when i == 100 } @again; // this is a label // this code will be executed forever jump again; // move execution to the @again label
There are two additional flow-control mechanisms. The first is the state transition, which we already covered. The second is the return command, which we will cover in the section "Advanced Language Features." In all of the flow-control examples, the decision of which path to take was determined by the value of an expression. In LSL, an expression is a combination of operators and functions. Functions will be explained in more detail in the "Advanced Language Features" section. Operators are divided into several broad categories. As with other categories, the LSL Wiki covers this in great detail (http://lslwiki.com/lslwiki/wakka.php?wakka=operators).
Operator Types
Unary
Unary operators are arithmetic operators that modify one value, as in the following example:
integer count = 1; // create a new integer variable and assign it the value of 1 count++; // the "++" operator adds 1 to "count" and assigns the result to "count" llSay(0, (string)count); // says "2" -- note the type conversion
Binary
Binary operators are arithmetic operators that act on two values to produce a third, as shown here:
integer a = 5; integer b = 2; integer c = a % b; // compute a modulo b, so c = 1
Boolean
Boolean operators always generate TRUE (1) or FALSE (0) results:
integer a = 5; integer b = 2; integer c = a != b; // "!=" returns TRUE if its arguments are not the same.
Bitwise
Bitwise operators act on the bitfields that make up integers. Here are some examples:
integer a = 5; // 0x101 in binary integer b = 2; // 0x010 integer c = a | b; // a or b = 0x111, so c = 7
Assignment
Finally we have the assignment operators, which take the result of an expression and assign it to a variable. In addition, LSL supports several variants of the assignment operator that perform an arithmetic operation along with assignment, as in the following example:
integer a = 5; // assigns 5 to a a += 5; // adds 5 to a, then assigns the result, so a = 10