1234.56789
1234.0
123.0e+5
NULL is a special keyword that indicates that there is no reference to the object.
Exceptions are made up of a parent type and a limited set of sub-types:
Exception | Parent exception type; catches any kind of exception |
Undef_Exception | An exception with an unknown type or unknown cause. A runtime exception. |
Type_Exception | Caused by attempting to store the wrong type. |
Perm_Exception | Permission denied |
Div_Exception | Division by zero |
Float_Exception | Floating point math error |
Field_Exception | Field not found on object |
Method_Exception | Method not found on object; signature doesn't match |
Range_Exception | Out of bounds on string or list |
Null_Exception | Invalid reference; NULL reference exception |
3 + 4
7
"Some string"
{"list", "of", "mixed", 7183, "type"}
l[1]Malformed or bad expressions can raise an exception. If the exception is uncaught, it will cause a undefined exception and the script engine will halt execution of the script.
integer | 0 |
float | 0.0 |
string | "" |
list | {} |
object | NULL |
dict | {} |
rtree | {} |
exception | Undef_Exception |
Variables are declared with the following (C-like) syntax:
type variable;
type variable = expression;
Variables are local to their scope (code-block in which they are declared).
Variable names may be contain any character inside the set:
0-9, A-Z, a-z, '_'
Variable names may start with any character inside the set:
A-Z, a-z, '_'
more properly
[A-Za-z_][A-Za-z0-9_]*
Variable declarations are expressions and return the default or initialized value of the variable (as part of the behavior of the assignment operator).
The logical and ('&') and logical or ('|') operators modify truth
expressions according to this table:
1 & 1 => 1
1 & 0 => 0
0 & 0 => 0
1 | 1 => 1
1 | 0 => 1
0 | 0 => 1
{...} | list declaration | list |
x.y, x.y() | property, method | object |
x[i], x[i..j], @ | index, range, splice | list and string |
- | unary negation | integer or float |
*, /, % | mult., div., modulo | integer or float |
+, - | add, cat, subtract | integer, float, or string |
isa | is same heritage | any object |
in | inside list | any against list |
<, <=, >, >=, ==, != | comparison | any same (checks content) |
! | logical negation | integer |
& | logical and | any expression |
| | logical or | any expression |
= | assignment | any same |
The list declaration operator takes the comma delimited expressions and creates a list type.
The property and method accessors return the value of the property or invocation of the method.
The list and string indexing operator returns the value of the element in the list or string at the given integer index.
The range indexing operator returns a list or string containing copies of the elements inside the list.
The splicing operator allows lists to be merged.
Unary negation converts an integer or float to its negated form.
Multiiplication, division, and modulo operations perform the appropriate math on the integer or float values inside the expression. In mixed types, integers are cast to floats and a float is returned for the entire expression.
Addition and subtraction operations perform the appropriate math on the integer or float values inside the expression. In mixed types, integers are cast to floats and a float is returned for the entire expression.
Concatenation occurs with strings. The left-side string will have the right-side string appended, and a new string value will be returned.
isa operations occur with objects. If the left-side object is a child of the right-hand object, true is returned.
in operations occur with lists (and in for-loops, where it acts as an iterator). If the left-side value is in the list, the index of the value is returned, otherwise 0 is returned.
Comparison operators work on any value of the same type. Strings will be compared against the ASCII table. Integers and floats will be compared numerically. Lists will be compared by length.
The logical negation operator will invert the truth value of an expression.
Logical and and logical or operators are explained above, in the Truth section.
The assignment operator will assign the value of the right-side of the expression to the field or variable on the left side of the expression. The entire assignment expression will be given the value of the right-side of the expression, as well, allowing code like:
x = y = z = 3
where x, y, and z are all assigned the value of 3.
list[index]
Index a single element from a list. This will
evaluate to the value of the item contained in the list at that index.
list[integer_1..integer_2]
Index a range of elements from a list. This will evaluate to a new
list containing those items inside that range (copies).
list[index] = expression
Assign a new value into this list at the integer index.
@list
Splices a list into a list (exposes list contents so they may be placed
in another list).
{@{1, 2, 3}} => {1, 2, 3}@list_1 = {@list_2, @list_3}
{1, 2, 3, 4, 5, 6} = {@{1, 2, 3}, @{4, 5, 6}}@list_1 = {list_2, @list_3}
{{1, 2, 3}, 4, 5, 6} = {{1, 2, 3}, @{4, 5, 6}}expression in list
"baz" in {"foo", "bar", "baz", "frobble"} => 3
"xyzzy" in {"foo", "bar", "baz", "frobble"} => 0
string[index]
Index a single substring (character) from a list. This will evaluate
to the character contained in the string at that index.
string[start_index..end_index]
Returns a substring from the start index to the end index.
Some special object values are available, as well:
this | retrieves a reference to the object containing the method |
super | refers to the parent class for the object, but is only valid for invoked a parent implementation of an overloaded method |
registry | retrieves a reference to the object registry |
Transient objects are not written to the database and have temporary references (object ids). They can be converted to persistent objects with the make_persistent() function call. This will break references to the transient object but will store its data in a persistant manner.
Persistent objects are written to the database and have permanent references (object ids). They can be converted to transient objects with the make_transient() function call. This will break references to the persistant object and its data will no longer be stored in a persistant manner.
Persistant objects also may have an aliased form.
Network objects are references to objects on other servers. They may be transient or persistent on their home server, but are considered transient on this server--that is, their contents are not saved to the local database.
object o = #transient_id | Assigns the transient object given by the id to the o object variable. |
object o = #persistent_id | Assigns the persistent object given by the id to the o object variable. |
object o = $object_alias | Assigns the persistent object given by the alias to the o object variable. |
object o = server_name#object_id | Assigns the network object given by the id to the o object variable. |
Transient object ids are made up of alphabetic characters. These values are not guaranteed to be identical between instances of the server.
\#[A-Za-z]+Example: #hsyUJwjsIOl
Persistent object ids are made up of numeric characters and are guaranteed to be the same between instances of the server.
\#[0-9]+Example: #928372912
Aliased object ids are made up of alphanumeric characters, starting with the $ character followed by an alphabetic character. These are guaranteed to be identical between instances of the server and apply to persistent objects only.
  \$[A-Za-z][A-Za-z0-9]*Example: $avatar
Network objects are made up of a server name and either a persistent or transient object id. Server names are either DNS names, IP addresses, or hostnames.
(([A-Za-z][A-Za-z0-9\-\.]*)|([0-9][0-9]?[0-9]?\.?)+)Example: server.domain.org#291827
\$[A-Za-z][A-Za-z0-9]*Example: $avatar Example: server.domain.org$avatar
Objects can change classes with the chparent() function call. Properties (fields) missing on the new parent class will be removed with the potential loss of data.
New classes are defined with the add_class() function call. Classes are redefined with the same function call. Classes can only be created locally.
Classes may be removed with the rm_class() function call. Classes may not be removed if they have any child classes or objects that reference them.
Classes may change their parents with the chclass() function call. Classes may only change to a new parent no property or method definitions are lost in this change.
object.field_name
object.(string_field_name)
In the first form, the field name is hard coded. In the second, the field name is specified by a string literal or variable.
Setting a field value may be done by:
object.field_name = expression
object.(string_field_name) = expression
As with any assignment, the value of the assignment expression is available as the value of this entire expression.
expression = object.method(expression_n, ...)
Methods return one value of any one type. Methods, by default, will return integer 0 in the absence of any other return statement. If the method called was not found on the object, Method_Exception will be thrown.
Methods may also be called with a string literal expression (like field values):
expression = object.(method)(expression_n, ...)
A special method call is available to invoke the parent implementation of this same method.
expression pass(expression)
This will invoke the parent implementation with the expression as arguments
(comma delimited values). If there is no parent implementation, Method_Exception
will be thrown. The pass statement will return the value returned by the parent
method.
expression = function(param_n, ...)
The simplest, legal statement is a semicolon:
;The next simplest statement is an expression followed by a semicolon:
expression;In this case, the expression is evaluated and its value is ignored.
A code block is defined as code within an opening curly brace ('{') and closing curly brace ('}'). These allow a number of statements to execute within the same scope, as well as limit variables to a local scope.
{ statements }
Statements containing expressions that raise exceptions will throw the expression to its containing code block.
if (expression) {
statements
}
if (expression) {
statements
} else {
statements
}
if (expression) {
statements
} else if (expression) {
statements
} else {
statements
}
Example:
if (x < 5) {
<statements>
} else if (x > 1) {
<statements>
} else {
<statements>
}
while (expression) {
statements
}
list evens = {};
integer n = 1;
while (n <= 5) {
evens = {@evens, 2 * n};
}
evens => {2, 4, 6, 8, 10}
"for" allows looping across a list expression:
for variable in (list_expression) {
statements
}
The variable is given the value of the list element under consideration.
list odds = {1, 3, 5, 7, 9};
list evens = {};
integer n;
for n in (odds) {
evens = {@evens, n + 1};
}
evens => {2, 4, 6, 8, 10}
"for" also allows looping across an integer range:
for variable in [range_low..range_high]
{
statements
}
list evens = {};
integer n;
for n in [1..5] {
evens = {@evens, n * 2};
endfor
evens => {2, 4, 6, 8, 10}
All loop structures allow the statements "break" and "continue" to modify loop behavior.
break;
Break breaks out of the loop and continues executing the script after the loop.
continue;
Continue skips the rest of this iteration of the loop and continues
with the next iteration.
In order to catch exceptions, they must be inside a code block defined
by an exception handler ("try").
try {
statements
} catch (exception-type variable) {
statements
} finally {
statements
}
This will declare the specified variable as an exception of the specified exception type and assign the variable's value to the be that of the exception thrown.
To catch any kind of exception, declare the exception of type "Exception", otherwise, to catch a specific type of exception, declare it to that type. You may specify as many catch clases as needed.
The finally clause will execute regardless of any exceptions thrown
and is optional.
integer x;
try {
x = 1; // this is legal
x = "foo!"; // this is illegal
} catch (Type_Exception e) {
// notify the user about the exception
} finally {
x = 0; // make sure that the value is legal regardless
}You can use multiple catch clauses for different exceptions, but only one finally clause per try statement. You can embed try statements in outer try statements in order to catch additional exceptions.
Methods have signatures that uniquely identify how they are invoked. A signature is composed of the declaring object, the method name, and the method arguments (defined by order and type).
A method may access its arguments with the special list variable
args which is created when the method is invoked.
// get the first argument, defined as a string in the signature
string name = args[1];
// get a count of the number of arguments passed into this method
integer argcount = length(args);
// pass the argument list to the parent implementation of this method
pass(@args);
return;
return expression;
Return followed by some expression will immediately exit the method and return the provided expression. Return without an expression will return an integer 0.
return; => 0
return "Foo!"; => "Foo!"
fork () {
statements
}
fork (integer_seconds) {
statements
}
fork will start a new asynchronous task after the specified number of seconds have elapsed, or at the earliest opportunity. This task will execute the code contained in the fork statement's code block at that time.
Code following the fork function will be executed immediately following the fork function call and will not wait for the fork to finish processing.
fork returns the integer task id of the running task so that it can
be managed.
integer get_task()
integer suspend(integer_seconds)
integer suspend(integer_seconds, integer_task_id)
This will cause the specified task to pause execute for at least the given number of seconds. If the number of seconds specified is less than 1, the task will pause for an indefinite period.
If no task_id was provided, the currently running task will be paused.
This function returns true if the task was successfully paused.
If you attempt to modify a task you don't own, a Perm_Exception is thrown.
integer resume(integer_task_id)
This will attempt to resume a paused task immediately.
This function returns true if the task was successfully resumed.
If you attempt to modify a task you don't own, a Perm_Exception is
throw.
integer kill(integer_task_id)
This will cause the specified task to stop execution immediately and exit.
This function returns true if the task was successfully resumed.
If you attempt to modify a task you don't own, a Perm_Exception is
throw.
string to_string(expression)
float to_float(expression)
integer to_integer(expression)
These functions will perform with a greater or lesser degree of success depending on the expression provided. Lists will have their members concatenated into one single string expression prior to evaluation. Strings will evaluate to a float or integer if in the set of characters:
0-9, '-', '+', 'e+', 'e-', '.'
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?)
At the first non-numeric-legal character, the remainer of the string
is ignored.
to_integer("4552foo") => 4552
to_float("4552foo") => 4552.0
to_integer("32.56980") => 32
to_float("32.56980") => 32.5698
to_integer("washu100") => 0
to_float("washu100") => 0.0
Returns the length of a list.
Returns the length of a string.
Aliases the specified object with the given string alias. Returns true (1) if the alias was set and available, false (0) otherwise. Use unalias_object() clear an alias.
integer add_class(string class_name, string parent_class)
Creates a new class name. Returns true (1) if the class was successfully added, false (0) otherwise (for instance, if the class name was already defined). Only local classes may be created, but the parent class can be a network class assuming that the network class name (when localized...that is, with the network name removed) does not conflict with local classes. This will copy the parent class to the local server class name does not conflict.
integer chclass(string class_name, string new_parent)
Changes the class heritage. Returns true (1) if the class was successfully changed, false (0) otherwise. This will not be possible if any inherited method definitions (signatures) or field declarations (names) change.
integer chparent(object_id, string new_parent)
Changes the object's parent. Returns true (1) if the class was successfully changed, falase (0) otherwise. Fields and methods that are not present on the new parent class will be shed.
object_id create(string class_name, persistent_indicator)
Creates a persistent or transient object as a child of the given class_name. If the persistent_indicator is true (1), the object will be a persistent object, else if will be a transient object.
persistent_id make_persistent(transient_id)
Converts a transient object and data contents into a persistent object. The data is copied from the old object to the new object. Changes to the presistent data do not propagate to the transient object and vice versa.
transient_id make_transient(persistent_id)
Converts a persistant object and data contents into a transient object. The data is copied from the old object to the new object. Changes to the persistent data do not propagate to the transient object and vice versa.
integer rename_class(old_class_name, new_class_name)
Renames the class. Returns true (1) on success, false (0) on failure. The new class name may not conflict with any other existing class names or this will fail.
integer rm_alias(string alias)
Removes the specified alias from the registered aliases. Returns true (1) if successful, false (0) if the alias was not present.
integer rm_class(string class_name)
Removes the specified class from the system if it has no child classes or child objects. Returns true (1) on success, false (0) otherwise.
integer valid(object_id)
Returns true (1) if the object with the given id exists, false (0) otherwise. If the object id provided is an alias that does not exist, returns false (0).