Skip to content

New compiler's end user cheat sheet

ivan-mogilko edited this page Jul 2, 2022 · 10 revisions

This is an end-user friendly reference of the new script compiler's features and script syntax changes. Base on the information from Features of the new Script Compiler.

Structs

Nested regular structs

Both regular and managed structs can now contain nested regular structs:

struct Pair { 
    int X, Y; 
};

struct TwoPairs {
    Pair p1;
    Pair p2;
};

managed struct ManagedStruct {
    TwoPairs tp;
};

IMPORTANT: Currently there is still an engine limitation that prevents managed structs from containing other managed structs (pointers to structs) or managed arrays.

Auto Pointers

You may now omit * symbol when declaring pointers to managed structs. So, for instance, instead of

ManagedStruct* obj;

you can write simply

ManagedStruct obj;

and compiler will guess that it's a pointer, as managed structs may only be used as pointers in script.

IMPORTANT: Currently the big exception is import declarations. There's a internal issue in AGS script: the built-in script are allowed and because of it you must declare imports of type or returning type with

Implied this in struct functions

You can now omit this when writing struct functions and want to reference this struct's member variable or function:

struct Warrior {
    int Health;
    bool Dead;
    import function LooseHealh(int hp);
};

function Warrior::LooseHealh(int hp) {
    Health -= hp;
    if (Health < 0) {
        Dead = true;
    }
}

Arrays

Multi-dimensional arrays

You can have multi-dimensional non-dynamic arrays:

You can declare or equivalently,. .

// Declare two-dimensional array of size 5x3
int a[5, 3];
int b[5][3];

You can have any positive number of dimensions, e.g. int a[2][3][5][7][11];

Accessing elements is done similarily to declaration, that is:

int a[5, 3];
int e11 = a[1, 1];
int e23 = a[2][3];

Dynamic array's Length

Dynamic arrays now have Length property that returns their length:

int arr[];

arr = new int[10];

int length = arr.Length;

Variable definitions

You can now define global variables right after the struct or enum declaration, for example:

struct Pair { 
    int X, Y; 
} pair1, pair2, pair3; // declares 3 global variables of type Pair
enum TrafficLightColour
{
    red,
    amber,
    green,
} col1, col2, col3; // declares 3 global variables of type TrafficLightColour

Compile-time evaluations

Compiler can now evaluate integer or float expressions at compile time whenever result is actually constant and can be calculated at compile time. This allows to use expressions where syntax normally requires a constant. For example:

int arr[7 * 9 + 1]; // the size of array will be calculated by compiler

New keywords

fallthrough in switch

In switch, the compiler tries to find out whether code execution falls through the end of a non-empty case into the next case. Such "fall through" is usually unintended (a break; is missing). So the compiler warns when it detects the situation. In order to shut up the warning and declare that the fall through is intended, you can code fallthrough; immediately in front of the next case.

Examples:

switch(inventory_item)
{
case iBlueCup: // no statements inside, falling through, but is fine
case iYellowCup:
    player.Say("I fill the cup with water.");
    break; // break present, all is good
case iVase:
    player.Say("I fill the vase with water.");
    // missing break, will yield a warning
case iBigTowel:
    player.Say("That's my favourite towel. Oh well...");
    fallthrough; // fallthrough keyword tells compiler that it's intended
case iSmallTowel:
    player.Say("The towel is now wet.");
    break;
default:
    player.Say("I think this is useless.");
}

New operators

Pre-Increment and pre-decrement operators

Previously compiler supported only post-increment and -decrement: x++ and x--; The new compiler also supports pre-increment and -decrement: ++x and --x;

The difference between these is that if this operation is used in another expression:

  • With post-increment/decrement: the old variable's value will be used in calculation, and variable changed afterwards.
  • With pre-increment/decrement: the variable will be changed and its new value will be used in calculation.

For example:

int x = 5;
int a = x++; // a = 5, x becomes 6
int b = ++x; // x becomes 7, b = 7

Bitwise negation

Bitwise negation is ~ operator, which converts each bit in the value to its opposite: 1 to 0 and 0 to 1.

Ternary conditional operator

The classic ? : ternary operator is now supported. Standard form: foo = (x > 5) ? 1 : 2; means that foo is set to 1 if (x > 5), to 2 otherwise. Can leave out the second part of a ternary so that "?" and ":" go right next to each other. For instance, int foo = bar ?: 15; This means that foo is normally set to bar, but if bar is 0 or null then foo is 15 instead. Particularly handy for specifying a default in case a pointer variable turns out to be null. (This is the same functionality as the ?? operator in C#.)

Expressions

Function calls as partial expressions

If the function returns a managed object, you can now directly access properties and functions of returned object in the same expression.

For example: Character.GetAtScreenXY(x, y).Walk(100, 200);

Also sequences can now be undefinitely long.

Concatenated string literals

String literals that are next to each other (separated only by whitespace) are treated as if they were one concatenated string literal.

player.Say("Hello" " world");  // same as "Hello world"