Difference between revisions of "LavishScript:Language and Engine Overview"

From Lavish Software Wiki
Jump to navigation Jump to search
Line 78: Line 78:
 
  call InitializePerson Jimmy 12 TRUE
 
  call InitializePerson Jimmy 12 TRUE
 
  echo ${If[${Returned},"InitializePerson successful","InitializePerson failed"]}
 
  echo ${If[${Returned},"InitializePerson successful","InitializePerson failed"]}
 +
 +
=== Special types of functions ===
 +
There are 4 types of functions in LavishScript, each defined in the same way, but with their own keyword: <tt>function</tt>, <tt>atom</tt>, <tt>member</tt>, and <tt>method</tt>.  Here's a little tree to show you how these types of functions are related:
 +
* function
 +
** atom
 +
*** member
 +
*** method
 +
As the tree indicates, an atom is a function, and members and methods are atoms.
 +
 +
Here's the differences.  A '''function''' is simply a segment of code.  A function is not guaranteed to execute to completion before anything else happens -- it may be broken up by the scheduler to run on subsequent frames, and functions are also allowed to use certain commands that force a delay.  Because of this, a function cannot be used directly in a data sequence (which begin with ${ and end with }), because data sequences are ''atomic''.  When something is atomic, it cannot be broken up (in this case, meaning that it cannot wait until a subsequent frame).  An '''atom''' therefore is an atomic function.  The difference is simply that it ''is'' guaranteed to execute to completion immediately, cannot use delays, will not be broken up by the scheduler, and so on, and therefore an atom ''can'' be used in a data sequence.  '''Members''' and '''methods''' are specialized atoms for use with objects, which have the advantage of natively being used in data sequences.
  
 
== Variables ==
 
== Variables ==

Revision as of 01:51, 19 April 2006

Introduction

LavishScript is designed for a mixed, hostile environment. That is, an environment where objects and types of objects may be forcefully removed without notice by an external source. For example, as part of an addon to a game that was not meant to have addons, with scripts to automate gameplay and such. Safety is ensured by discarding object references after use (as each data sequence is closed).

LavishScript is pre-emptively scheduled and also has a concept of atomic code sequences. Pre-emptive scheduling is necessary to allow a script to run "in the background" iteratively while a game plays, as opposed to a purely event-based paradigm, though it is possible to create fully event-driven scripts as well.

LavishScript's structural syntax is derived from C, with statement syntax derived from command-line interpreters.

LavishScript is object-oriented. Each piece of data is an object, and each type of object (object type, also known as data type) may have various operations or other objects associated with it, by containment or otherwise. Object types can be created via script, or in C++. Object types follow a single-inheritance model (though special handling can be used for object types created in C++ to use any sort of inheritance). Object sub-types can be used to create an object that uses another type (compare to C++ templates), such as a collection of strings.

The Language

Preprocessor

LavishScript includes a built-in preprocessor. The preprocessor's job is to take input (generally a file), and apply given transformations (such as word replacements, macros, pre-selection of portions of code, insertion of additional files, and so on), sending the output to the engine for final processing. See the preprocessor page for a complete reference to the LavishScript preprocessor.

Comments

Comments are a method of introducing plain text into code for human readability, and are completely ignored by the script processor. LavishScript supports two types of comments.

ANSI-C Comments

ANSI-C comments begin with /* and end with */. This style of comment may begin and end anywhere (including in the middle of other lines) without restriction, but may not be nested. For some tips on using ANSI-C comments, see Standards and Style for Coding in ANSI C.

/* This is an ANSI-C Comment */
/********************************
 *                              *
 *          So is this          *
 *                              *
 ********************************/
/*
 * And this
 */

Full-line Comments

Full-line comments begin with a ; as the first non-whitespace character on a line, and end naturally at the end of the line. This style of comment cannot be used in the middle of a line.

; This is a full-line comment
echo hi; This is NOT a full-line comment

Object type definitions

Types of objects can be defined as part of a script. These object types will only be available for object creation or typecasting within their owning script, but objects of these types can be accessed anywhere within scope of the object. Object scopes are discussed in the Variables section below.

Object type definitions begin with the keyword objectdef, followed by the name of the type of object, such as

objectdef character

Inheritance can be specified by using the keyword inherits, followed by the name of the script-defined object type to inherit, such as

objectdef player inherits actor

The lines immediately following the objectdef line describe the contents of the new object type. They may contain variables, functions, methods, members and atoms. The contents of the objectdef begins with a line containing only {, and ends with a line containing only } (referred to as a code block).

The following is an example of a valid, empty object definition:

objectdef player inherits actor
{
}

Functions

A function is a sequence of code to be executed. Function definitions begin with the keyword function, followed by the name of the function, along with a set of parentheses such as

function MoveTo()

The parentheses are actually to contain a list of parameters, separated by commas. Each parameter becomes a local variable when the function is eventually called. Each parameter definition begins with the name of an object type, such as string, followed by the name of the parameter, such as Name. The following is an example of a function with parameters:

function InitializePerson(string Name, uint Age, bool Male)

This example has three parameters, a string called Name, a uint called Age, and a bool called Male. It would presumably keep a record of some personal information entered in a user interface.

To assign a default value to a parameter if not all parameters are given to the function, follow the name of the parameter with = and the default value, like so

function InitializePerson(string Name, uint Age, bool Male=TRUE)

To accept a variable number of parameters to a function, use ... as the object type, as the last parameter, such as:

function HowManyParameters(... Params)

The variable will be an array of strings, with the size equal to the number of parameters actually given to the function.

All functions have the ability to return an object. By default, the return type is string. To return another type of object, append the function keyword with a colon, followed by the object type (this is the same construct as object sub-types), like so

function:bool InitializePerson(string Name, uint Age, bool Male=TRUE)

The returned object is initialized to the object type's default (empty, zero, etc) value when the function is called, and can be directly accessed via an object called Returning. The Return command can be used to end execution of the function at any point -- if the command is used without following parameters, the return object is returned unchanged. If parameters are used, the original object is destroyed, and a new object is given, initialized with the parameters given. The object can be retrieved from the calling function with the Return object.

Immediately following the function line, a code block must be given, beginning with a { line and ending with a } line. The following is a complete example of a function:

function:bool InitializePerson(string Name, uint Age, bool Male=TRUE)
{
  echo ${Name} is ${Age} years old and is ${If[${Male},male,female]}
  return TRUE
}

Function code blocks may contain variables and statements to execute.

To call a function, use the Call command, followed by the function name, and then any parameters, like so:

call InitializePerson Jimmy 12 TRUE
echo ${If[${Returned},"InitializePerson successful","InitializePerson failed"]}

Special types of functions

There are 4 types of functions in LavishScript, each defined in the same way, but with their own keyword: function, atom, member, and method. Here's a little tree to show you how these types of functions are related:

  • function
    • atom
      • member
      • method

As the tree indicates, an atom is a function, and members and methods are atoms.

Here's the differences. A function is simply a segment of code. A function is not guaranteed to execute to completion before anything else happens -- it may be broken up by the scheduler to run on subsequent frames, and functions are also allowed to use certain commands that force a delay. Because of this, a function cannot be used directly in a data sequence (which begin with ${ and end with }), because data sequences are atomic. When something is atomic, it cannot be broken up (in this case, meaning that it cannot wait until a subsequent frame). An atom therefore is an atomic function. The difference is simply that it is guaranteed to execute to completion immediately, cannot use delays, will not be broken up by the scheduler, and so on, and therefore an atom can be used in a data sequence. Members and methods are specialized atoms for use with objects, which have the advantage of natively being used in data sequences.

Variables

A variable is an object created of a given type for use in LavishScript. This differs from built-in objects (referred to as Top-Level Objects), which are simply there, or added by a LavishScript module.

Variables can be created as part of script structure, or dynamically while a script is running with the DeclareVariable command. This section will detail creating variables as part of script structure.

Variables are placed into one of five "scopes", which describe where the variable exists, and where it does not. When the scope of the variable is destroyed, the variable is destroyed too. The five variable scopes are as follows:

  • local
Exists only within a function. This scope is default (and the only scope available) when declaring a variable within a function.
  • object
Exists only within a script-defined object. This scope is default (and the only scope available) when declaring a variable within an object type definition (not within one of its functions)
  • script
Exists only within a script. This scope is only available outside of functions or object type definitions, and is default in that case.
  • global
Exists globally, but destroyed with the owning script. This scope is only available outside of functions or object type definitions.
  • globalkeep
Exists globally, not destroyed with the owning script. This scope is only available outside of functions or object type definitions.

Variables are defined with the variable keyword, followed by the type, and finally the name of the variable, like so:

variable type name

Where type is the object type to use, and name is the name to use. Variables may be initialized to given values on creation by adding an equals sign (=) and the default value. For object types that allow variable initialization with multiple parameters, these must be separated by spaces (follow basic LavishScript Command Syntax for parameter grouping). To specify a different scope for the variable, the scope is placed in parentheses and attached to the end of the variable keyword, like so:

variable(globalkeep) string MyString="Initialize to value"

In the above statement, a global variable that will be detached from the script is created, called MyString, of the string object type, and initialized to Initialize to value.