Skip to main content

Execution

What happens when your program runs: how numbers behave, how memory is managed, the limits you can hit, and what is and isn't deterministic.

int big = 9223372036854775807;
int wrapped = big + 1; // wraps to -9223372036854775808
int q = 7 / -2; // -3: integer division rounds toward zero
float inf = 1.0 / 0.0; // Infinity, no error
int hits = 3;
int misses = 0;
int r = hits / misses; // traps: misses is 0

Running a program​

Before anything runs, the whole program is checked. Any compile error in any loaded file stops it from starting. Then the host starts an entry point (gameMain, uiMain or main).

Your scripts behave the same whether they are interpreted, translated to machine code as they load (JIT), or compiled ahead of time into the game executable (AOT) (see deployment modes); only speed and start-up time differ. Debug builds behave the same too, but run slower so that stepping matches your source.

A running program cannot be changed in place. To pick up script changes, the host recompiles and restarts the program.

Numeric semantics​

int​

  • Signed 64-bit.
  • +, -, * and unary - wrap around on overflow.
  • / rounds toward zero: 7 / -2 == -3, -9 / 2 == -4.
  • % takes the sign of the left operand: -7 % 3 == -1.
  • / and % by zero trap. So does dividing the minimum int by -1.

int32​

  • Signed 32-bit.
  • +, -, *, / and unary - wrap around on overflow, including the minimum int32 divided by -1.
  • / and % by zero trap.

byte​

Values 0 to 255. Arithmetic on bytes gives an int. Storing an int in a byte takes byte(x), which keeps the low 8 bits (byte(300) is 44).

float​

  • 64-bit double precision with standard IEEE 754 rounding.
  • Never traps: dividing by zero gives infinity, 0.0 / 0.0 gives NaN, and NaN carries through further maths. The literals NaN and Infinity name these values directly.
  • % doesn't work on floats; use fmod or remainder from math.
  • math functions never fail; they return NaN or infinity where the maths requires. Functions such as sin and exp may differ in the last digit between Windows and Linux.
  • Integers above 2^53 lose precision when converted to float.

float32​

  • 32-bit single precision with standard IEEE 754 rounding; otherwise the same rules as float.
  • A math call whose float arguments are all float32 returns float32.

Memory​

  • Memory is automatic. There is no manual allocation or freeing and there are no pointers.
  • Objects, arrays, maps, strings and the like are freed by a garbage collector once nothing refers to them, including objects that only refer to each other in a cycle.
  • There are no destructors and you can't tell when something is freed. Close files, sockets and processes explicitly; use && { ... } so cleanup always runs.
  • A slice keeps its whole array alive; a task keeps the objects it uses alive until it finishes; a channel keeps its queued values alive.
  • Running out of memory traps.

Limits​

LimitValueIf you hit it
Values a single function can hold at once (parameters, locals, temporary results and distinct constants)255function 'NAME' needs more than 255 frame slots .... Split the function into smaller ones.
Nesting depth of brackets, blocks and operators256nesting is too deep (limit 256). Move inner parts into helper functions.
Recursion depthGrows as needed, up to a share of system memoryTrap -3. Use a loop or an explicit stack.
Integer literal9223372036854775807integer literal ... is out of range
Array, map and buffer sizeint, bounded by memoryOut of memory traps.

Determinism​

You can rely on:

  • left-to-right evaluation (see Evaluation order);
  • select choosing the earliest ready arm;
  • first-in, first-out order in channels and Mutex;
  • map reads and writes behaving the same from run to run.

You cannot rely on:

  • the order in which tasks interleave or which ready task runs first;
  • the order in which a for ... in loop visits a map's keys;
  • when memory is freed.

Timers, file and network I/O, and engine events come from outside the program. If your result must be the same every run, order dependent work with join, channels or a Mutex rather than relying on timing.

See also​