Control Flow
Control flow statements are used to control the flow of execution in a program.
Parentheses
Parentheses can be used to group statements together and to control the order of execution.
let x = 1 + 2 * 3
let y = (1 + 2) * 3
// x is 7, y is 9
Multiple Statements
Parentheses can also be used to execute multiple statements in sequence. The last expression in the block determines the resulting value of the parentheses.
let x = (
let a = 1
let b = 2
Print { "Hello, world!" }
a + b
)
// x is now 3
You can use semicolons to separate statements on the same line. This is the same example as above, but with semicolons instead of newlines:
let x = (let a = 1; let b = 2; Print { "Hello, world!" }; a + b)
Parentheses define a new scope, so after the parentheses end, all variables declared inside of it will be deallocated and will no longer be accessible:
let x = (
let a = 1
a + 123
)
let y = a + 456 // Error: unknown identifier `a`
Multi-valued Expressions
Use commas to return multiple values from a parentheses block:
let x, y = (1, 2 + 3)
// x is 1, y is 5
You can have multiple statements before the final expression when returning multiple values as well:
let x, y = (
let a = 1
let b = 2 + 3
a, b
)
// x is 1, y is 5
Block scopes
Use curly braces to create a new scope. When the scope ends, all variables inside of it will be deallocated and will no longer be accessible.
pub game fn World.Main() {
let a = 2, b = 3
{
let c = a + b
DoSomethingWith(c)
}
// Variable `c` is not accessible here
}
If you want to create a scope inside an expression, use parentheses instead of curly braces:
pub game fn World.Main() {
let a = 2, b = 3
// Use parentheses to create a block scope inside an expression
let output = (
let c = a + b
DoSomethingWith(c)
c // The last expression determines the resulting value
)
// Braces in an expression create a Map, which is why you have to use parentheses instead of braces
let x = { apple = 123, banana = 456 }
}
If statements
The if statement is used to execute a block of code if a condition is truthy.
let x = 5
if x > 3 {
Transmission { "x is greater than 3" }
}
// Outputs "x is greater than 3"
An else clause can be added to execute a block of code if it fails to match all other conditions.
let x = 5
if x > 3 {
Transmission { "x is greater than 3" }
} else {
Transmission { "x is less than or equal to 3" }
}
// Outputs "x is greater than 3"
else if blocks can be added to test multiple conditions.
let x = 7
if x > 10 {
Transmission { "x is greater than 10" }
} else if x > 5 {
Transmission { "x is greater than 5" }
} else {
Transmission { "x is less than or equal to 5" }
}
// Outputs "x is greater than 5"
If expressions
When if is used in an expression, the last value of each block is returned as the value of the expression.
let x = 7
let a =
if x < 10 {
let prefix = "more than"
prefix + " 10"
} else {
"10 or less"
}
If there is no else block, the resulting value will be undefined.
let x = 99
let a = if x < 10 { "less than 10" }
// a is `undefined`
Use commas to return multiple values from an if expression:
let x = 7
let a, b =
if x < 10 {
"less than 10", -10
} else {
"10 or less", 10
}
// a is "less than 10", b is -10
Repeat statements
The repeat loop is used to execute a block of code a fixed number of times.
repeat 5 {
Transmission { "Hello, world!" }
}
// Outputs "Hello, world!" 5 times
Repeat expressions
When repeat is used in an expression, the break statement determines the resulting value of the expression.
If the loop exists without a break, the resulting value will be undefined.
let x = 3
let a = repeat {
if x < 10 {
break 5
}
}
// a will be either `5`
While statements
The while loop is used to execute a block of code while a condition is truthy.
let x = 0
while x < 5 {
Transmission { %(x) }
x += 1
}
// Outputs 0, 1, 2, 3, 4
While expressions
When while is used in an expression, the break statement determines the resulting value of the expression.
If the loop exists without a break, the resulting value will be undefined.
let a = while Tick < 10s {
if that.Pos.X > 100 {
break 100
}
}
// a is either `100` or `undefined` depending on whether the condition was met before the loop ended
For statements
The for loop is used to execute a block of code for each element in a collection.
for x in Range(0, 5) {
Transmission { %(x) }
}
// Outputs 0, 1, 2, 3, 4
The for loop variable can be declared as a context variable by prefixing it with use:
pub fn Example() {
for use x in Range(0, 5) {
TakeXFromContext
}
// Outputs 0, 1, 2, 3, 4
}
pub fn TakeXFromContext([x]) {
Transmission { %(x) }
}
You can provide two loop variables to iterate over the index and value of an Array:
let list = ["Potato", "Tomato", "Banana"]
for index, value in list {
Transmission { %(index + ": " + value) }
}
// Outputs "0: Potato", "1: Tomato", "2: Banana"
You can also iterate over the keys and values of a map using two loop variables:
let map = { potato = 123, banana = 456 }
for key, value in map {
Transmission { %(key + ": " + value) }
}
// Outputs "$potato: 123", "$banana: 456"
For expressions
When for is used in an expression, the break statement determines the resulting value of the expression.
If the loop exists without a break, the resulting value will be undefined.
let list = [1, 2, 3, 4, 5]
let a = for x in list {
if x == 3 {
break 100
}
}
// a is either `100`
Loop statements
The loop statement is used to execute a block of code indefinitely.
let x = 0
loop {
Transmission { %(x) }
x += 1
if x >= 5 {
break
}
}
Loop expressions
When loop is used in an expression, the break statement determines the resulting value of the expression.
let a = loop {
if Tick > 10s {
break 100
}
await Tick
}
// a is now `100`
Break statements
The break statement is used to exit a loop early.
It can be used with repeat, while, and for loops, as well as on and with blocks.
let x = 0
while true {
Transmission { %(x) }
x += 1
if x == 5 {
break
}
}
// Outputs 0, 1, 2, 3, 4
Pass an expression to break to specify the resulting value of the loop expression.
let a = loop {
if Tick > 10s {
break 99
}
await Tick
}
// a is now `99`
You can pass multiple values to break to return multiple values:
let x, y, z = loop {
if Tick > 10s {
break 1, 2, 3
}
await Tick
}
// x is 1, y is 2, z is 3
Continue statements
The continue statement is used to skip the rest of the current iteration of a loop.
It can be used with repeat, while, and for loops, as well as on and with blocks.
let x = 0
while x < 5 {
x += 1
if x == 3 {
continue
}
Transmission { %(x) }
}
// Outputs 1, 2, 4, 5
Surprise statements
A surprise block is used to randomly choose between multiple options.
Only one of the options will be executed.
The simplest form of a surprise block is a list of options.
All options are given equal chance of being selected.
surprise {
ShieldPowerup,
TriblastPowerup,
}
Weighted Random
It is possible to assign weights to each option to control the likelihood of each option being selected.
surprise {
2 => TriblastPowerup,
1 => ShieldPowerup,
}
In this example, the TriblastPowerup is twice as likely to be selected as the ShieldPowerup.
Multiple Statements
Each option can be a block of code instead of a single statement:
surprise {
{
Print { "You got a Triblast Powerup!" }
TriblastPowerup
},
{
Print { "You got a Shield Powerup!" }
ShieldPowerup
},
}
Surprise Expressions
A surprise block can also be used as an expression, in which case the resulting value will be the value of the selected option.
The last expression of the block determines the resulting value of the option.
let x = surprise {
{
Print { "You got an apple!" }
"apple"
},
{
Print { "You got a banana!" }
"banana"
},
}
// x is either "apple" or "banana", chosen randomly
Use commas to return multiple values from a surprise block:
let name, points = surprise {
{
Print { "You got an apple!" }
"apple", 100
},
{
Print { "You got a banana!" }
"banana", 200
},
}
// Either name="apple" and points=100, or name="banana" and points=200, chosen randomly
Specifying the Random Number Stream
You can also provide an ID to the surprise block to choose its random number stream.
See Random Number Generator Streams
surprise<apple> {
Smitten,
Poisoned,
}