Deeper Into LSL
Now we'll focus on compilation, uploading, and execution (Figure 8.2). LSL is a scripting language that runs server-side, on a piece of software called the simulator. The simulator does just what it's name implies -- it simulates the virtual world of Second Life. Each simulator runs everything for 16 acres of virtual land -- buildings, physics, and of course, scripts. While you manipulate the script text in a form that is somewhat easy to read, the actual code that runs on the simulator is compiled. A compiler is a piece of software that takes the text version of the script and converts it into something that can actually run. In the case of LSL, the compiler exists within the Second Life viewer itself. In the future, it is likely that the compiler will move from the viewer into the Second Life simulators, but where the code is compiled isn't very important. What matters is that the text is converted into a form that can run on the simulators.
Compilers also serve the function of detecting errors in the code you've just written. Although compilers can't detect all errors, it can detect common mistakes like syntax errors (Figure 8.3). Let's return to our "Hello, Avatar!" script. We can introduce a syntax error in many ways, but one example would be to remove the trailing brace, }, from the end of the state_entry event. Since we have modified the text, the Save button lights up; click on it to attempt to compile the text. Rather than the "Compile successful, saving_" and then "Save complete." we've become accustomed to, we instead see "(7, 4) : ERROR : Syntax error" and the cursor moves to the first letter of the touch_ start event.
What does all this mean? The "(7, 4)" tells us that the error is at or near row 7, column 4 of the script, which we also know because the cursor has been positioned there. The "Syntax error" tells us that we've probably made a relatively simple typing error. If we examine our script, we see that the braces don't match. The compiler, upon reaching the touch_start event, was expecting a trailing brace, so it flagged this as an error and stopped compiling the script. Notice something else. If you exit the Build tool and click on the box, it fails to respond with "Touched." When a script fails to compile, Second Life stops executing the script on the target object. This is to reduce confusion and prevent broken or mismatched scripts from continuing to operate with Second Life. Simply add the trailing brace back in and save the change to both fix the error and to recompile the script.
When a script properly compiles, it generates LSL bytecode. Bytecode is a simple form that is relatively easy to execute. In the future, LSL may compile to a different form for execution, but that won't change how you write scripts. It will simply change how Second Life handles things under the hood. Why would we be contemplating these types of changes? Performance, primarily. LSL currently executes quite slowly, so we will continue to make changes to improve what you can do within LSL.
Either way, once the compiled code is on a simulator, it can actually be executed. Execution is simply the process of checking to see whether the script needs to do anything. In our example script, when an avatar clicks on the box, Second Life checks to see if any touch event handlers exist. Since one does (touch_start), the code within the handler executes. Once that code is complete, the script goes to sleep until it needs to do something else.
This process of doing work only when required is key to both how LSL is structured and to writing good LSL scripts. It requires you to understand states and events, however. We'll discuss states first. As was covered earlier, all LSL scripts need to have at least one state, denoted by the default keyword. A state is a collection of code between the opening and closing braces of the state. In its simplest form, a script has a single state and all of its code lives there.
For example, imagine that you are creating a script to manage a very simple door that you touch to open or close. Using states can clarify what your code does:
// default state is closed default { touch_start(integer tnum) { // insert code to open the door here // . . . state open; } } state open { touch_start(integer tnum) { // insert code to close the door here // . . . state default; } }
Note that this is different from the traditional way of writing this, where you would maintain whether the door was open or closed in a global variable, something like this:
// default state is closed integer is_closed = TRUE; default { touch_start(integer tnum) { if (is_closed == TRUE) { // insert code to open the door here // . . . is_closed = FALSE; } else { // insert code to close the door here // . . . is_closed = TRUE; } } }
In this simple case, it may look like the global variable option is easier, but when other behavior also has to change between the open and closed state, splitting the code into multiple states is much simpler than having to wrap everything in if statements.
These code samples illustrate some other basics of LSL syntax. First, the "//" denotes a comment. A comment allows you add text to your script to remind you of why you wrote the code a particular way, to lay groundwork for later coding (such as "insert code to open the door here"), or to make it easier for someone else to follow your work. Note that only the text to the right of the "//" is part of the comment, allowing comments to be added to a line that contains code. For example, in the line
state open // this is entered when the door opens "// this is entered when the door opens" is the comment.
Second, we introduce global variables and the variable type "integer." Global variables, like is_closed, are available anywhere in the code. They are similar to global variables in other programming languages, such as C, and they can be any of the types available to LSL (see the section "What Are Types?"). LSL is a statically and strongly typed language, meaning that variables are given types when created and generally require typecasting to convert between types.