A statement is something that performs an action. A semicolon character (;) is used to separate statements.
Block statement
The most commonly used kind of statement is a block statement. It begins with a left curly brace ({) and ends with a right curly brace (}).
{
const a = 7 + 5;
const b = a * 4;
{
const c = (b - a) / 2;
print c;
}
}
print statement
print is a statement that prints the result of the expression into the log.
print "Hello world!";
print("Good evening.");
print 2 + 2;
Functions for manipulating and reading runtime information.
Definition Application.dox:8
INFO: Hello world!
INFO: Good evening.
INFO: 4
INFO: <class Application>
Control flow statements
Statements can be used to introduce control flow into a script. In HSL, the following statements are control flow statements:
- if: Executes a statement if a condition is a truthy value.
- else: Executes a statement if the condition of an if statement was not a truthy value.
- switch: Matches a value with case labels.
- continue: Finishes the current iteration of a loop.
- break: Interrupts execution of a loop or switch.
- return: Interrupts the execution of a function, and return a value.
if and else statements
An if executes the statement that follows it if the expression between the parentheses is a truthy value. Otherwise, if there is an else statement following it, it executes that instead.
if (expression)
statement
else if (expression)
statement
else
statement
else if is actually two statements together: else and if. An if condition may be followed by multiple else if conditions.
if (expression)
statement
else if (expression)
statement
else if (expression)
statement
else if (expression)
statement
else
statement;
To execute multiple statements after an if or else statement, a block statement is required.
if (expression) {
statement1
statement2
statement3
}
else if (expression) {
statement1
statement2
}
else {
statement
}
switch statement
A switch statement matches the expression with case labels:
switch (expression) {
case expression1:
statement;
break;
case expression2:
statement;
break;
case expression3:
statement;
break;
default:
statement;
break;
}
When a case is matched, the statements inside it are executed until a break statement is found.
var drink = "juice";
switch (drink) {
case "water":
print "Drinking water.";
break;
case "juice":
print "Drinking juice.";
break;
case "soda":
print "Drinking soda.";
break;
}
If there is no break statement, the execution falls through to the next case label, even if the expression in the case does not match the expression in switch.
var drink = "juice";
switch (drink) {
case "water":
print "Drinking water.";
case "juice":
print "Drinking juice.";
case "soda":
print "Drinking soda.";
}
INFO: Drinking juice.
INFO: Drinking soda.
If none of the cases are matched, the default label is executed, if there is any.
var drink = null;
switch (drink) {
case "water":
print "Drinking water.";
break;
case "juice":
print "Drinking juice.";
break;
case "soda":
print "Drinking soda.";
break;
default:
print "Not drinking anything.";
break;
}
INFO: Not drinking anything.
There cannot be multiple default labels in a switch.
var drink = null;
switch (drink) {
case "water":
print "Drinking water.";
break;
case "juice":
print "Drinking juice.";
break;
case "soda":
print "Drinking soda.";
break;
default:
print "Not drinking anything.";
break;
default:
print "No drink?";
break;
}
A case or default label can return instead of break. This exits the entire function the switch is in.
event calculate(a, b, operation) {
switch (operation) {
case "plus":
return a + b;
case "minus":
return a - b;
case "multiply":
return a * b;
case "divide":
return a / b;
}
}
print calculate(5, 2, "plus");
Declarations cannot be written inside of a switch statement, without using a block.
event calculate(a, b, operation) {
switch (operation) {
case "plus":
var result = a + b;
return result;
case "minus":
var result = a - b;
return result;
case "multiply":
var result = a * b;
return result;
case "divide":
var result = a / b;
return result;
}
}
Using a block after a label lets you use declarations:
event calculate(a, b, operation) {
switch (operation) {
case "plus": {
var result = a + b;
return result;
}
case "minus": {
var result = a - b;
return result;
}
case "multiply": {
var result = a * b;
return result;
}
case "divide": {
var result = a / b;
return result;
}
}
}
print calculate(5, 2, "plus");
continue statement
A continue statement finishes the current iteration of a loop, and begins the next iteration.
repeat (10, counter, remaining) {
print "Counter: " + counter;
if (counter < 7) {
continue;
}
print "Loop will end in " + remaining;
}
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
INFO: Counter: 3
INFO: Counter: 4
INFO: Counter: 5
INFO: Counter: 6
INFO: Counter: 7
INFO: Loop will end in 3
INFO: Counter: 8
INFO: Loop will end in 2
INFO: Counter: 9
INFO: Loop will end in 1
break statement
A break statement exits a loop immediately.
repeat (10, counter) {
print "Counter: " + counter;
if (counter == 3) {
print "Stopping.";
break;
}
}
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
INFO: Counter: 3
INFO: Stopping.
break can also exit a switch.
event printWeekday(weekday) {
switch (weekday) {
print "Start of business days";
print "Weekday";
break;
print "Weekend";
}
}
@ WEEKDAY_WEDNESDAY
Definition WEEKDAY.hsl:24
@ WEEKDAY_SUNDAY
Definition WEEKDAY.hsl:12
@ WEEKDAY_SATURDAY
Definition WEEKDAY.hsl:36
@ WEEKDAY_FRIDAY
Definition WEEKDAY.hsl:32
@ WEEKDAY_TUESDAY
Definition WEEKDAY.hsl:20
@ WEEKDAY_THURSDAY
Definition WEEKDAY.hsl:28
@ WEEKDAY_MONDAY
Definition WEEKDAY.hsl:16
INFO: Start of business days
INFO: Weekday
INFO: Weekday
INFO: Weekday
INFO: Weekend
A break is not necessary on the last case label, since the switch will exit anyway.
return statement
A return statement ends the execution of a function, and optionally specifies a value to be returned. At most one value can be returned from a function.
event returnHello() {
return "Hello";
}
var hello = returnHello();
print(hello);
If return is followed by a semicolon (;) instead of an expression, null is returned.
var result;
event divide(a, b) {
if (b == 0) {
return;
}
return a / b;
}
result = divide(10, 2);
print(result);
result = divide(7, 3.0);
print(result);
result = divide(5, 0);
print(result);
INFO: 5
INFO: 2.333333
INFO: null
Top-level code cannot be returned from.
var a = 10;
var b = 2;
if (b == 0) {
return;
}
var result = a / b;
print(result);
Loop and iteration statements
A loop is a way to execute a specific piece of code many times. The simplest kind of loop is a repeat, but there are conventional while, do-while, and for loops as well.
repeat loops
A repeat loop executes its statement a specific amount of times. In its basic form, it looks like the following:
repeat (expression)
statement
For example, the following code prints "Hello world!" three times:
repeat (3) {
print "Hello world!";
}
INFO: Hello world!
INFO: Hello world!
INFO: Hello world!
A repeat loop can also be written as the following:
repeat (expression, counter, remaining)
statement
counter and remaining are optional. They are variables that can be provided in a repeat loop. counter is an integer that counts up from zero, and remaining is an integer that counts down from the initial value.
print "First loop:";
repeat (3, counter) {
print "Counter: " + counter;
}
print "Second loop:";
repeat (3, counter, remaining) {
print "Counter: " + counter;
print "Remaining: " + remaining;
}
INFO: First loop:
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
INFO: Second loop:
INFO: Counter: 0
INFO: Remaining: 3
INFO: Counter: 1
INFO: Remaining: 2
INFO: Counter: 2
INFO: Remaining: 1
Be careful when using a decimal as the repeat amount, as repeat checks if remaining is equal to zero, not if it's lower than or equal to zero:
repeat (3.5, counter) {
print "Counter: " + counter;
}
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
INFO: Counter: 3
INFO: Counter: 4
INFO: Counter: 5
INFO: Counter: 6
INFO: Counter: 7
INFO: Counter: 8
INFO: Counter: 9
INFO: Counter: 10
...
remaining can be assigned to during an iteration.
repeat (10, counter, remaining) {
print "Counter: " + counter;
if (counter == 3) {
print "Skipping iterations...";
remaining = 3;
}
}
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
INFO: Counter: 3
INFO: Skipping iterations...
INFO: Counter: 4
INFO: Counter: 5
Notice how counter still counted up to five. Even if remaining is modified, it will still increment by one on each iteration. counter, however, cannot be assigned to.
repeat (10, counter) {
print "Counter: " + counter;
if (counter == 3) {
print "Skipping iterations...";
counter = 8;
}
}
while and do-while loops
A while loop executes its statement as long as its condition evaluates to a truthy value. The condition is checked before the iteration.
var i = 0;
while (i < 3) {
print "Hello world!";
i++;
}
INFO: Hello world!
INFO: Hello world!
INFO: Hello world!
A do-while loop is the same as a while loop, but its statement executes at least once, and then the condition is checked after the iteration.
var i = 4;
do {
print "Hello world!";
i++;
} while (i < 3);
var j = 4;
while (j < 3) {
print "Hello world!";
j++;
}
for loops
A for loop consists of three expressions. Typically, the first expression initializes a loop counter, the second expression checks the loop counter, and the third expression increments the loop counter.
for (initialization; condition; increment)
statement
Any of the three statements can be omitted. This kind of for loop does the following:
- Run the code in the initialization expression, if present. Variables are allowed to be declared with var here.
- The condition expression is executed, if present. If it evaluates to a falsey value, the loop finishes here.
- statement is executed. This can be a block statement.
- increment is executed, if present.
- Go back to step 2.
The following for loop is equivalent to the repeat example you saw earlier:
for (var counter = 0; counter < 3; counter++) {
print "Counter: " + counter;
}
INFO: Counter: 0
INFO: Counter: 1
INFO: Counter: 2
The following is also a valid for loop:
var counter = 0;
for (; counter < 3;) {
print "Counter: " + counter;
counter++;
}
So is the following:
var counter = 0;
for (;;) {
print "Counter: " + counter;
counter++;
if (counter == 3) {
break;
}
}
for-in loops
A for-in loop iterates through an object.
for (value in iteratable)
statement
Examples of objects that can be iterated in this manner are arrays, maps, and instances. When used with an array, this iterates through its contents.
for (string in [ "foo", "bar" ]) {
print(string);
}
When used with a map, this iterates through its values.
for (value in { "foo": 123, "bar": 456 }) {
print(value);
}
To iterate through the keys of a map, use the keys() method.
var map = { "foo": 123, "bar": 456 };
for (key in map.keys()) {
print(key + ": " + map[key]);
}
INFO: foo: 123
INFO: bar: 456
You may make any instance iteratable by defining iterate and iteratorValue methods in its class. Example:
class Bookcase {
Bookcase() {
this.Books = [
"How To Boil Eggs",
"The Chicken That Crossed The Road",
"Coping With Brooding"
];
}
iterate(state) {
if (state == null) {
state = 0;
}
else {
state++;
}
return null;
}
return state;
}
iteratorValue(index) {
return this.Books[index];
}
}
var bookcase = new Bookcase();
for (book in bookcase) {
print book;
}
A resizable list of values.
Definition Array.dox:8
integer Length(array array)
Gets the length of an array.
INFO: How To Boil Eggs
INFO: The Chicken That Crossed The Road
INFO: Coping With Brooding
How for-in works is as following:
- iterate is called. When the iteration begins, null is passed to state. If the iteration was already ongoing, state is the value that iterate last returned.
- If iterate returns null, the iteration ends.
- iteratorValue is called. The value that iterate returned is passed to index. It must return the value that will be used in this iteration.
- If the loop wasn't interrupted using break or return, go back to step 1.
Declaration statements
In HSL, the following statements are declaration statements:
- var: Declares a variable. Assignment is optional.
- const: Declares a constant variable. Requires assignment with a constant expression.
- local: Declares a variable or a constant in script scope.
- event: Declares a function or a method.
- class: Declares a class.
- enum: Declares an enumeration.
- import: Imports a script or a class.
- using: Places the classes or constants of a namespace into global scope.