Hot++

Types

Hot++ has fixed-width builtin types. Other types come from C++.

Parts of this guide

This guide has 2 pages. This page covers builtin types, variables, C++ types, collection literals and arrays.

Builtin types

Type Alias Note
bool    
sbyte int8  
byte uint8  
short int16  
ushort uint16  
int int32 5
uint uint32  
long int64 5L
ulong uint64  
nint, nuint   pointer size
float   5.0
double   5.0d
char, wchar   8 bit and 16 bit
void   no value

null is the empty handle.

The C++ spellings with many words are errors, for example unsigned int and long long. The message gives the script type: use uint or long. A native virtual method with an unsigned parameter matches a script override with uint.

Integer arithmetic and casts

Integer operations have no undefined behavior in a script, except where this section says so.

The shift check and the divide check are always on, also with HOT_RUNTIME_CHECKS=0. The translator skips a check when it can see that the check is not needed: a shift by a literal count in range, or a float operand. A class with its own << or >> operator (a stream, for example) keeps the operator.

MSVC has no -fwrapv. The script compile in an MSVC build does not guard signed overflow. MSVC does not use signed overflow for optimization in practice, so a wrap is the result there too.

The implicit conversion from a float to an integer is not checked. Use a cast (see Limits).

Variables

A variable can have no initializer. It then gets the default value (zero, false, null). var takes the type from the initializer. Do not write const on a variable. The translator infers it: a local that the body never assigns is const. The error const is inferred; remove it shows when you write it.

class Demo {
    int hp = 100;
    ulong id = 7;
    float speed = 5.0;         // 5.0 is float, 5.0d is double
    double ratio = 0.5d;
    long big = 5L;
    int count;                 // default value: 0

    void Run() {
        var x = 3;             // int
        int limit = 10;        // never assigned: the translator makes it const
    }
}

C++ types

Use . for a scope. The translator writes :: and -> for you.

class Names {
    std.string name = "demo";
    std.vector<int> list = std.vector<int>();
}

string, vector and the other headers in Module level need no using.

Type aliases

using Name = type; names a type (see Module level). An alias is the type that it names. using Soldier = $Recruit; is a handle. using Soldier = Recruit; is a value.

class Recruit {
    int hp = 3;
}

using Squad = std.vector<$Recruit>;   // a vector of handles
using Soldier = $Recruit;

class Platoon {
    Squad squad;
    Soldier lead;
}

Script classes in templates

A template argument $Child is a handle. std.vector<$Child> holds one handle for each element. The rule also works inside other templates, for example std.map<int, std.vector<$Child>>.

using <vector>;

class Child {
    int hp = 3;
}

class Parent {
    std.vector<$Child> kids = std.vector<$Child>();

    void Run() {
        this.kids.push_back(new $Child());
        foreach (var k in this.kids) { k.hp += 1; }
        this.kids[0].hp = 9;
    }
}

Collection literals

[a, b] builds a list. [k: v] builds a map. [] is empty. The C++ type comes from the declaration, so a literal needs a typed local, a typed field initializer or a place inside another literal. var x = [1, 2]; is an error.

using <map>;

class Tables {
    std.vector<int> ids = [1, 2, 3];
    std.map<std.string, int> score = ["a": 1, "b": 2];

    void Run() {
        std.vector<std.vector<int>> grid = [[1, 2], [3]];
        std.vector<int> none = [];
    }
}

Arrays

T[N] is an array of N values of type T. The size N is an integer literal. The C++ type is std::array<T, N> by default. The module attribute array sets another type (see The array type). T[M][N] is an array of M arrays of N values.

class Grid {
    int[4] cells;
    float[3] v = [1.0, 2.0, 3.0];
    int[2][3] table;

    int Sum() {
        int sum = 0;
        foreach (var x in cells) {
            sum += x;
        }
        return sum + cells.size();
    }
}

These rules apply to an array:

Views

T[] is a view of values of type T. The C++ type is hot::span<T> by default. It works with C++17. A view does not own the values. See The view type for the option that selects std::span<T>.

A view is valid for a parameter, a return type and a local. The owner of the values is a std.vector<T>, a T[N] or another view. A std.vector<T> or a T[N] converts to a T[] at a call or at a local declaration.

using <vector>;

class Stats {
    int Sum(int[] values) {
        int sum = 0;
        foreach (var x in values) {
            sum += x;
        }
        return sum;
    }

    void Double(int[] values) {
        foreach (ref x in values) {
            x *= 2;
        }
    }

    int Run() {
        std.vector<int> list = [1, 2, 3];
        int[3] fixed;
        int[] head = list;
        Double(head);
        Double(fixed);
        return Sum(list) + Sum(fixed) + head[0];
    }
}

These rules apply to a view:

The view type

hot::span<T> is the default C++ type of T[]. It is in hot/runtime/span.h. It has these properties:

You can select std::span<T> instead. Use the CMake option HOT_VIEW_TYPE=std. These rules apply:

See CMake options for the option HOT_VIEW_TYPE.