Variables
Variables are created on demand and don't need to be explicitly declared. Sometimes the host will insert
known global variables before the script is run, but that usage pattern is declining as "Main" functions
are now used, that allow parameters from outside the script to be passed in via explicit method arguments.
The variables themselves are based on a variant data type, that can contain integers, strings and various
pointer types. There is no dereference operator needed to use a pointer type variable. Pointer arithmetic
is not supported, as generally the pointers are to single class objects, not arrays of objects. That said
there are List and HashTable sub-types to the variables, but no array as such.
Scope
There are 3 fixed scopes: global, local, register. Although in practice when writting code you only ever
deal with global and local. Unlike C, there are no extra scope levels inside { } blocks inside a function.
Variables defined in that function (including it's arguments) are visible throughout that function.
Global variables are defined outside of a function scope and are visible everywhere.
Constructs
Scripts are constructed from these primitives:
if (expression) { statements; }
[else if (expression) { statements; }]
[else { statements; }]
while (expression)
{
statements;
}
for (initial_expression; condition_expression; iterate_expression)
{
statements;
}
function method_name([arg1, arg2, ...])
{
statements;
[return expression;]
}
struct structure_name
{
type member1;
[type member2; ... ]
};
extern "dynamic_library" return_type method_name([type arg1, type arg2, ...]);
return expression;
expression;
Operators
These operators can be used in expressions:
= | Assign
|
+ | Plus
|
- | Minus
|
* | Multiply
|
/ | Divide
|
% | Mod
|
< | LessThan
|
<= | LessThanEqual
|
> | GreaterThan
|
>= | GreaterThanEqual
|
== | Equals
|
!= | Not Equals
|
+= | Plus Equals
|
-= | Minus Equals
|
*= | Multiply Equals
|
/= | Divide Equals
|
++ | Post Increment
|
-- | Post Decrement
|
++ | Pre Increment
|
-- | Pre Decrement
|
&& | And
|
|| | Or
|
! | Not
|
. | Object member reference
|
Objects
Some variant types allow the referencing of object members or methods via the '.' operator.
The available members depends on the variant type:
- DOM:
- "member_name" - depends on the object, they all have different member names.
For example see the Scribe Object Model.
- String:
- Length - the length of the string in bytes (strings are utf-8).
- Int - the string as an int (atoi).
- Float - the string as a double (atof).
- Split(<separator>[, <max_split>]) - Splits the string into a list.
- Join(<list>) - Joins all the elements in 'list' using the string as a separator.
- Find(<sub-string>[, <start>[, <end>]]) - Finds a sub-string.
- Strip() - Removes all leading and trailing whitespace.
- Upper() - Converts all alpha characters to upper case.
- Lower() - Converts all alpha characters to lower case.
- Int:
- String - the int as an string.
- Float - the int converted to floating point.
- Double:
- String - the double as an string.
- Int - the double converted to integer.
- List:
- Length - the number of objects in the container.
- Add(<element>) - Add a new element to the end of the list.
- Delete(<index>) - Deletes the entry at 'index'.
- HashTable:
- Length - the number of objects in the container.
- Add(<key>, <element>) - Add a new element using the string 'key'.
- Delete(<key>) - Deletes the element at using the string 'key'.
- DateTime:
- Year - just the year as an int.
- Month - just the month as an int.
- Day - just the day as an int.
- Hour - just the hour as an int.
- Minute - just the minute as an int.
- Second - just the second as an int.
- Date - the date part as a string.
- Time - the time part as a string.
- DateTime - the date and time as a string (also responds to the name "string").
- TimeStamp - a 64bit int timestamp of the date (also responds to the name "int").
- Second64Bit - the size of a second when comparing timestamps.
- Image (GSurface):
- x - The width in pixels.
- y - The height in pixels.
- Bits - The bit depth.
- ColourSpace - The surface's colour space (a LColourSpace variable as a uint32)
List
The list object type allows you to store a bunch of objects in a variable (of the same variant type).
To get the length of the list, use
var_name.length, and to access the various
members use
var_name[
index_expression] where the exp
evaluates to an integer. If you don't specify an
integer then you'll get back a NULL variable as the
result.
HashTable
HashTable's are very similar to lists, in that they allow you to store a objects in a variable.
To get the number of objects in the hash table, use
var_name.length,
and to access the various members use
var_name[
index_expression]
where the exp evaluates to an
string. If you don't specify a string then you'll get back a NULL
variable as the result.
Built In Types
These types can be used in defining structures and parameters to external functions:
- int
- short
- long
- int8
- int16
- int32
- int64
- uint8
- uint16
- uint32
- uint64
- bool / boolean
- double
- float
- char*
- void*
- LDom
- LDateTime
- LHashTable
- LOperator
- LView
- LMouse
- LKey
- LVariant
Some of these types don't have any implementation or testing done. Integers and strings should work fine though.
Custom Types
You can define structures in a similar fashion to C code using the
struct keyword. For
example:
struct PxRgb24 {
uint8 r;
uint8 g;
uint8 b;
};
struct Image
{
uint32 Width;
uint32 Height;
PxRgb24 Pixels[16 * 16];
};
Packing of structures is currently on 1 byte boundaries, but it would be possible to implement other settings later.
The
typeid(...) keyword is supported for custom types. e.g.
Obj = New("Image");
if (Obj)
{
Type = typeid(Obj);
Print("TypeName=" + Type.Name + ", sizeof=" + Type.Length + "\n");
Delete(Obj);
}
TypeName=Image, sizeof=772
Calling extern functions
To call methods in dynamic libraries you first have to declare the method using the extern keyword:
extern "dynamic_library" type method([type arg1, type arg2, ...]);
The types for extern functions are somewhat limited to these keywords:
- char*
- int, int32, uint32, int64, uint64
- double
- void*
- _out_ (specifies that the argument is an output, rather than an input)
More type support will be added as needed. All non-char pointers will become "void*". The dynamic_library will
be passed to "dlopen" or "LoadLibrary" pretty much unchanged.
Windows based example:
extern "Kernel32.dll" uint32 GetWindowsDirectoryA(_out_ char *buffer, int size);
buf = New(256); // Allocate a buffer for the return value
r = GetWindowsDirectoryA(buf, buf.Length);
Print("Dir='"+buf+"'");
Dir='c:\Windows'
Casting between types
There is limited support for casting between these types: int, string, date and double. The syntax is just:
my_str.int;
my_str.double;
my_int.string;
my_int.double;
my_dbl.string;
my_dbl.int;
my_date.int;
my_date.string;