# Lgi Scripting Syntax

## 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;
    }

    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.
- 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.
- Image (GSurface):
  - x - The width in pixels.
  - y - The height in pixels.
  - Bits - The bit depth.
  - ColourSpace - The surface's colour space (a GColourSpace 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*
- GDom
- void*
- GDateTime
- GHashTable
- GOperator
- GView
- GMouse
- GKey
- GVariant

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'