<a id="control-structures"></a>

# Control structures

A few language constructs are available in HSL in order to control program flow.

<a id="echo"></a>

<a id="id1"></a>

## echo

The `echo` statement will convert the expression to a string and print its value.

```default
echo expression ;
```

```hsl
echo "hello world";
```

<a id="if"></a>

<a id="id2"></a>

## if

One of the most basic control structures in HSL is the *if* statement, it allows conditional control flow. *if* statements check the expression for [truthiness](operators.html.md#truthtable).

```default
if (condition)
        statement
```

In addition to *if* there is also an *else* branch available; executed if the expression yields false

```default
if (condition)
        statements
else
        statements
```

```hsl
if (true) {
        echo "statement is true";
}
```

<a id="ternary-operator"></a>

### Ternary operator

The ternary operator is an expression and allows *expression branching*, if the *if_true_expression* is omitted (Elvis operator) then the value of *expression* is used if it tests positive for truthiness, also the expression is not re-evaluated.

```default
expression ? if_true_expression : if_false_expression
expression ? : if_false_expression
```

The ternary operator is right-associative with makes them stackable like if-else statements.

```hsl
$var = isset($arg) ? $arg : "default value";
```

<a id="null-coalescing-operator"></a>

<a id="id3"></a>

### Null coalescing operator

The null coalescing operator is an expression and allows *expression branching*, if the *variable* tests positive for [`isset()`](functions.html.md#isset) and is not a value of None (null) it is used. The expression which makes up the variable is not re-evaluated. There is also a [nullish coalescing assigment operator](operators.html.md#null-coalescing-assignment).

```default
variable ?? if_false_expression
```

The null coalescing operator is right-associative with makes them stackable like if-else statements.

```hsl
$data = json_decode(...);
$var = $data["settings"] ?? "default value";
```

<a id="for"></a>

## for

*for* statements allows conditional loops.

```default
for ( [initialization] ; [condition] ; [final-expression] )
        statements
```

```hsl
for ($i = 0; $i < 10; $i++) {
        echo $i;
}
```

<a id="break"></a>

### break

*break* will abort the loop iteration of a *for*, *foreach*, *while* and *forever* loop and also the execution of *switch* statements.

<a id="continue"></a>

### continue

*continue* will abort the current loop iteration of a *for*, *foreach*, *while* and *forever* loop, and restart on the next iteration.

<a id="foreach"></a>

<a id="id4"></a>

## foreach

*foreach* loops allows iteration on array values, object members (public and private depending on the execution context) and [`Iterator`](literals.html.md#Iterator) to execute the same statements multiple times.

```default
foreach (expression as $val)
        statements

foreach (expression as $key => $val)
        statements
```

```hsl
foreach (["Apple", "Banana", "Orange"] as $fruit) {
        echo $fruit;
}
```

<a id="id5"></a>

### break

*break* will abort the loop iteration of a *for*, *foreach*, *while* and *forever* loop and also the execution of *switch* statements.

<a id="id6"></a>

### continue

*continue* will abort the current loop iteration of a *for*, *foreach*, *while* and *forever* loop, and restart on the next iteration.

<a id="while"></a>

## while

*while* statements allows conditional loops.

```default
while ( expression )
        statements
```

```hsl
$i = 0;
while ($i < 10) {
        echo $i;
        $i += 1;
}
```

<a id="id7"></a>

### break

*break* will abort the loop iteration of a *for*, *foreach*, *while* and *forever* loop and also the execution of *switch* statements.

<a id="id8"></a>

### continue

*continue* will abort the current loop iteration of a *for*, *foreach*, *while* and *forever* loop, and restart on the next iteration.

<a id="forever"></a>

## forever

*forever* statements allows indefinite loops.

```default
forever
        statements
```

```hsl
$i = 0;
forever {
        echo $i;
        $i += 1;
}
```

<a id="id9"></a>

### break

*break* will abort the loop iteration of a *for*, *foreach*, *while* and *forever* loop and also the execution of *switch* statements.

<a id="id10"></a>

### continue

*continue* will abort the current loop iteration of a *for*, *foreach*, *while* and *forever* loop, and restart on the next iteration.

<a id="switch"></a>

## switch

*switch* statements are in many ways similar to nested if-else statements. *case* expressions are compared to the *switch* expression until a match is found. If no match is found, and a *default* label exists, it will be executed.

```default
switch (expression) {
        case expression:
                statements
        break;
        case expression:
                statements
        break;
        default:
                statements
        break;
}
```

If executing a statement and *break* is omitted the control flow will fall-through to the next statement.

<a id="match"></a>

## match

*match* expressions are in many ways similar to *switch* statements, however *match* is an expression and must result in a value.
If no match, and no optional *default* label exists an exception will be thrown.
Each match expressions may include multiple expression to be compared to seperated by a comma.

```default
$variable = match (expression) {
        compare-expression => value-expression;
        compare-expression, compare-expression => value-expression;
        default => value-expression;
}
```

```hsl
echo match (5) {
        0, 2, 4, 6, 8 => "even",
        1, 3, 5, 7, 9 => "odd"
};
```

<a id="include"></a>

## include

The *include* statement allows code to be structured in logical modules and shared between different scripts. The include path can be any of the supported *file* path formats (`file:X` where `file:` is implicit). *include*’s file name argument do not support variable interpolation nor expression since the include needs to be resolved at compile time. The statements in the included file are included in-place (replacing the *include* statement itself).

```default
include string ;
```

```hsl
include "file:1";
include "1";
```

> **Note**
> 
> The same file may be included multiple times. However cyclic inclusion is not permitted.

<a id="include-once"></a>

### include_once

The *include_once* keyword will only include the file if it hasn’t been included before.

```default
include_once string ;
```

<a id="import"></a>

## import

The *import* statement allows code to be structured in logical modules and shared between different scripts very much like *include_once* with the difference that all symbols which should be used in the calling script has to be explicitly imported. Also instead of running the imported code directly it is executed in a seperate context (with its own function and variable symbol table) referred to as “the module’s global scope”. If a file is imported multiple times (regardless of the symbols imported) its code will only be executed once (a behaviour which could be used to initialize global state), very much like *include_once* would behave. All symbols in a module’s symbol table is exported (by default), that include symbols which the module itself has imported from another module (a.k.a forwarding imports). An import can not be conditionally and must be defined unconditionally in the script (that usually means at the top of a script).

```default
import { symbol [ as symbol ] [ , ... ] } from string;
import * as symbol from string;
import variable from string [ with [ options ] ];
```

```hsl
import { foo, bar as baz, $x as $y } from "module";
import { $x as $y } from "module";
```

> **Note**
> 
> * The same file may be imported multiple times, but it will only be executed once. However cyclic inclusion is not permitted.
> * The path for the module may point to a folder, if so the file `main.hsl` in that folder is used.
> * The special syntax `./file.hsl` refer to a file in the same folder as the current file.

<a id="variables"></a>

### variables

A variable in the module’s global scope may be imported into the global scope. An imported variables is imported by reference (and not by value), hence all changes to the variable in the module will be reflected by the imported variable. An import statement is not allowed to overwrite variables in the local scope (if a conflict occures, it should be imported under another name).

```hsl
import { $x, $y as $z } from "module";
```

<a id="functions"></a>

### functions

A function in the module’s global scope may be imported into the global scope. An imported function (when executed) is executed in the module’s global scope. Hence, the *global* keyword imports from the module’s global context.

```hsl
import { v1, v2, v2 as vLatest } from "module";
```

<a id="wildcard"></a>

### wildcard

Wildcard imports (`*`) allows you to import all variables and functions from a module to a namespace (static class).

```hsl
import * as foo from "foo";
foo::bar();
echo foo::$x;
```

<a id="data-import"></a>

<a id="data"></a>

### data

All content in a module/file can be imported as a variable using different import methods at compile time (chosen by file extensions), this has the benefit of doing the data import once and the data shared across all executions.

```hsl
import $config from "config.json";
import $lookup from "lookup.csv";
import $data from "data.txt" with [ "type" => "array" ];
```

Currently there are data imports for the following file extensions.

| Extension/Loader   | Transformation      | Import type         |
|--------------------|---------------------|---------------------|
| json               | json_decode         | any                 |
| yaml               | yaml_decode         | any                 |
| csv                | csv_decode          | array               |
| txt                | *str_split*         | string/array/Set    |
| crt                | X509::String        | array of X509       |
| crl                | X509CRL::String     | array of X509 CRL   |
| eml                | MailMessage::String | MailMessage         |
| key                | \*_privatekey       | Privatekey resource |

While there are a lot of file extensions that do not have a loader (in the supported list above), it’s still possible to import any file using the syntax of *loader!file.ext* to override the selection of loader by *file extension* for that file (eg. `txt!logo.png` or `json!config.cfg`).

The .json import behaviour can be changed with the following options, default is to allow comments.

> * **objects** (boolean) If JSON objects should imported as objects (instead of arrays). The default is `false`.

The .yaml import behaviour can be changed with the following options.

> * **types** (array) Add support for the following predefined “tag” imports.
> 
> | Type          | Transformation        | Import type         |
> |---------------|-----------------------|---------------------|
> | `Map`         | Map()                 | Map                 |
> | `Set`         | Set()                 | Set                 |
> | `Regex`       | pcre_compile()        | Regex resource      |
> | `PrivateKey`  | \*_privatekey()       | Privatekey resource |
> | `X509`        | X509::String()        | X509                |
> | `X509CRL`     | X509CRL::String()     | X509CRL             |
> | `MailMessage` | MailMessage::String() | MailMessage         |

A sample import with types could look like this

```hsl
import $data from "myfile.yaml" with ["types" => ["Set", "Map", "Regex"]];
```

With the YAML tags defined as the following

```yaml
my-set: !Set
  - item1
  - item2
  - item3
my-map: !Map
  item1: !Regex /^pattern1$/
  item2: !Regex /^pattern2$/
```

The .csv import behaviour can be changed with the following options.

> * **delimiter** (string) The format separator. The default is `,`.
> * **header** (boolean) If the CSV data includes a header. The default is `true`.
> * **schema** (array) A [`csv_decode()`](functions.html.md#csv_decode) compatible CSV schema.

The .txt import behaviour can be changed with the following options.

> * **type** (string) Import the file line by line as an `array` (array type) or `set` ([`Set`](functions.html.md#Set) type) (without the CRLF or LF delimiter). The default is `string`.

The .crt import behaviour can be changed with the following options.

> * **resource** (boolean) Import the certificate as a `X509Resource` instead of `X509` object. The default is `false`.

The .crl import behaviour can be changed with the following options.

> * **resource** (boolean) Import the CRL as a `X509CRLResource` instead of `X509CRL` object. The default is `false`.

The .eml import behaviour can not be changed.

The .key import behaviour can not be changed.

> **Warning**
> 
> When import object such as `Map`, `Set` or `MailMessage`. Do *not* modify these objects. As these objects are shared between all script execution. And this object and operations are not thread-safe.

<a id="wildcard-file-imports"></a>

#### wildcard file imports

For all data imports, `glob` or sometimes called `fnmatch` patterns are supported. This allows you to import multiple resources into the same variable (supporting both id and `file://` matching). The resulting import will be an array where the data index on the file name.

```hsl
import $certs from "file://keys/*.crt";
// ["file://keys/1.crt" => X509, "file://keys/2.crt" => X509, ...]
```

<a id="user-function"></a>

<a id="function"></a>

## function

It’s possible to write new functions in HSL, and also to override builtin [functions](functions.html.md). A function may take any number of arguments and return a value using the [return](#return) statement. If non-variadic arguments are specified, the number of argument given by the caller must match the number of required arguments in the function definition.

```default
function funcname() {
        return expression;
}
function funcname($arg1, $arg2) {
        return expression;
}
function funcname(...$argv) {
        return expression;
}
```

> **Warning**
> 
> Recursion is not allowed.

<a id="named-functions"></a>

### Named functions

A function may be named (in order to be callable by its name) according to the regular expression pattern `[a-zA-Z_]+[a-zA-Z0-9_]*` with the exception of reserved keywords. In order to prevent naming conflicts in the future with added reserved keywords; it may be a good idea to prefix the function name with a unique identifier like `halon_func`.

`and` `array` `as` `barrier` `break` `builtin` `cache` `case` `class` `closure` `constructor` `continue` `default` `echo` `else` `false` `for` `foreach` `forever` `from` `function` `global` `if` `import` `include` `include_once` `isset` `match` `not` `none` `object` `or` `private` `readonly` `return` `switch` `true` `unset` `while` `with`

You *should* avoid using keywords available in other general purpose languages and they may be added in the future. That includes keywords such as *for*, *this*, *protected*, *public* etc.

<a id="function-scope"></a>

#### Function scope

Named functions are scoped either in the global scope (if not defined inside another function) or function scoped (a nested scope, may access functions in the previous scope). They are unconditionally registered at compile-time (control flow is not taken into consideration). Hence it doesn’t matter where in the scope it’s defined (eg. before or after it’s being called).

```hsl
funcname("World");
function funcname($name) {
        echo "Hello $name";
}
```

> **Note**
> 
> Named functions are “hoisted”.

<a id="anonymous-functions"></a>

### Anonymous functions

The syntax for [anonymous functions](literals.html.md#anonymous-functions) are the same as for named functions, with the exception that the function name is omitted. Hence they must be called by their value and not by name.

```default
function (argument-list) {
        return expression;
};
```

```hsl
$variable = function ($name) {
        echo "Hello $name";
};
$variable("World");
```

> **Note**
> 
> An anonymous function may be used as an *immediately-invoked function expression* (IIFE), meaning it may be invoked directly.
> 
> ```hsl
> echo function ($name) {
>         return "Hello $name";
> }("World");
> ```

<a id="closure"></a>

<a id="closure-functions"></a>

### Closure functions

The difference between an anonymous function and a closure function is that a closure function may capture (close over) the environment in which it is created. An anonymous function can be converted to a closure by adding the *closure* keyword followed by a capture list after the function argument list. These variables are captured by reference from the parent scope (function or global) in which they are created.

```default
function (argument-list) closure (variable-list) {
        return expression;
};
```

Most languages which implement closures capture (closes over) the entire scope (doesn’t use the concept of a capture list). HSL does not with the reasoning that all variables are function local; if the entire scope were to be closed over ambiguities could easily arise, and secondly it allows the developer to explicitly state the intention of the code.

```hsl
function makeCounter() {
        $n = 0;
        return [
                "inc" => function () closure ($n) { $n += 1; },
                "get" => function () closure ($n) { return $n; },
        ];
}
$counter1 = makeCounter();
$counter2 = makeCounter();

$counter1["inc"]();

echo $counter1["get"](); // 1
echo $counter2["get"](); // still 0, $counter2 hasn't been updated
```

> **Note**
> 
> This feature is similar to the PHP implementation of closures (*use*) however HSL’s *closure* statement captures by reference.

In order to capture by value, the following *immediately-invoked function expression* (IIFE) pattern may be used.

```hsl
$i = 3;
$f = function ($i) { return function () closure ($i) { return $i * $i; }; } ($i);
$i = 10;
echo $f(); // 3 * 3 = 9
```

<a id="return"></a>

<a id="id11"></a>

### return

The *return* statement return a value from a function. If the expression is omitted a value of *none* is returned.

```default
function funcname() {
        return [ expression ];
}
```

```hsl
function funcname() {
        return 42;
}
```

> **Note**
> 
> If the *return* statement is omitted and execution reached the end of the function, a value of *none* is returned. This is fine if the function is a *void* function.

<a id="default-argument"></a>

### Default argument

Formal parameters may be initialized with a default value if not given by the caller. Default values may only defined as trailing parameters in the function definition. Constant expressions which can be evaluated during compile-time may be used as default values (e.g. `$a = 10 * 1024` and `$a = []`).

```default
function funcname($arg1 = constant_expressions) {
        statements
}
```

```hsl
function hello($name = "World") {
        return "Hello $name.";
}
echo hello(); // Hello World.
echo hello("You"); // Hello You.
```

<a id="variadicfunction"></a>

<a id="variadic-function"></a>

### Variadic function

Arbitrary-length argument lists are supported using the `...$argument` syntax when declaring a function, the rest of the arguments which were not picked up by an other named argument will be added to the last variable as an array. This variable has to be defined at the end of the argument list.

```default
function funcname($arg1, ...$argN) {
        statements
}
```

```hsl
function avg(...$values) {
        $r = 0;
        foreach ($values as $v)
                $r += $v;
        return $r / length($values);
}

$values = [0, 5, 10, 15];
echo avg(...$values);
```

<a id="global-keyword"></a>

<a id="global"></a>

### global

The *global* statement allows variables to be imported in to a local function scope (by reference). If the variable is not defined at the time of execution (of the global statement) it will simply be marked as “global” and if later assigned; written back to the global scope once the function returns. If the variable that is imported to the function scope already exists in the function scope an error will be raised. If an imported variable is read-only, it will be read-only in the function scope as well.

```default
function funcname() {
        global $variable[, $variable [, ...]];
}
```

```hsl
function Accept() {
        echo "Message accepted";
        builtin Accept();
}
Accept();
```

<a id="function-calling"></a>

<a id="id12"></a>

### Function calling

<a id="argumentunpacking"></a>

<a id="argument-unpacking"></a>

#### Argument unpacking

Argument unpacking make it possible to call a function with the arguments unpacked from an array at runtime, using the *spread* or *splat* operator (`...`). The calling rules still apply, the argument count must match. This make it easy to override function.

```default
funcname(...expression)
$variable(...expression)
```

<a id="builtin-keyword"></a>

<a id="builtin"></a>

#### builtin

The *builtin* statement allows you to explicitly call the builtin version of an overridden function.

```default
builtin funcname()
builtin funcname
```

```hsl
function length($str) {
        echo "length called with $str";
        return builtin length($str);
}

echo length("hello");
```

<a id="id13"></a>

## `function*`

The `function*` statement declares a generator function, which returns a generator object. A generator object is an instance of a function that may *yield* or *return* multiple values. Generator functions support most of the function features available (eg. anonymous functions, default argument etc.). This manual may not be the best place to learn about generator functions in general as it more or less only describes our implementation of them.

```default
function* name() {
        yield or return
}
```

<a id="generator-object"></a>

<a id="id14"></a>

### generator object

A generator object ([`Iterator`](literals.html.md#Iterator)) is return when a generator function is called. It has one *next* method which invokes or resumes the generator function and returns the value of the next *yield* or *return* statement. If *yield* is used the function is suspended and the value from the yield statement is return. If *return* is used, the value is returned and the generator is finished (it may not be resumed).

> * **value** (any) The value returned from the generator function
> * **done** (boolean) The current state of the generator function

```hsl
function* infinity() {
        $i = 1;
        while (true)
                yield $i++;
}
$x = infinity();
echo $x->next(); // ["value"=>1,"done"=>false]
echo $x->next(); // ["value"=>2,"done"=>false]
```

Generator objects may be used with the `foreach` statement to iterate all its values, then the *value* will be the iteration variable of the foreach.

```hsl
function* counter($max) {
        $i = 1;
        while ($i <= $max)
                yield $i++;
}
$x = counter(5);
foreach ($x as $i)
        echo $i;
```

<a id="yield"></a>

### yield

The yield statement may be used to return multiple values from a generator function. If *return* is used within a generator function instead of *yield* the generator function is done and cannot be resumed with the *next* method.

```hsl
function* countdown() {
        yield 3;
        yield 2;
        return 1;
        yield 0;
}
$x = countdown();
echo $x->next(); // ["value"=>3,"done"=>false]
echo $x->next(); // ["value"=>2,"done"=>false]
echo $x->next(); // ["value"=>1,"done"=>true]
echo $x->next(); // ["value"=>,"done"=>true]
```

When the *yield* keyword is used as a expression, its value will be the generator objects *next* function argument. It may still yield a value.

```hsl
function* hello() {
        while (true)
            echo "Hello " . yield;
}
$x = hello();
$x->next(); // needed by pattern
$x->next("Alice");
$x->next("Bob");
```

<a id="exceptions"></a>

## Exceptions

The functionality of throwing and catching exceptions provide a mechanism to disrupts the normal execution flow on eg. error conditions.

<a id="try"></a>

<a id="id15"></a>

### try

```default
try {
        code
} catch (variable) {
        code
}
```

In order to catch an exception, it is has to be thrown within a *try*/*catch* code block. When a exception is thrown the remaining
code in the *try* statement is not execution and the execution flow is moved to the first statement of the *catch* code block.
Exception are catched at the first *catch* statement in the callstack, and are not propegated unless re-thrown.
If and exception is thrown outside of a *try*/*catch* code block it will result in a script error.

```hsl
try {
        echo "Hello";
        throw Exception("Error");
        echo "You"; // Never executed
} catch ($e) {
        echo "World";
}
```

<a id="catch"></a>

<a id="id16"></a>

### catch

The caught exception is available in the variable specificed in the catch statement.

```hsl
try {
        // throw here
} catch ($e) {
        echo $e;
}
```

<a id="throw"></a>

<a id="id17"></a>

### throw

Any value type may be thrown. Built-in runtime exceptions are instances of the [`Exception`](functions.html.md#_CPPv49Exception) class.

```hsl
try {
        throw "Hello World";
} catch ($e) {
        echo $e;
}
```

> **Note**
> 
> If throwing custom classes, any available toString() method may be called when logging the error.

<a id="class-statement"></a>

<a id="class"></a>

## class

The *class* statement can be used to declare new types of classes. The *class-name* must be a valid function name. In order to create a new instance of a class (object) call the class by name using the function calling convention. Class instances (objects) are not copy on write and all copies reference the same object. The default visibility of class members are public.

```default
class class-name
{
        constructor() {}

        $variable = initial-value;
        function function-name() {}

        private $variable = initial-value;
        private function-name() {};

        readonly $variable = initial-value;

        static $variable = initial-value;
        static function function-name() {}

        private static $variable = initial-value;
        private static function function-name() {}
}
```

> **Note**
> 
> Names of functions and variables may not conflict, as it will cause a compile error.

<a id="constructor"></a>

### constructor

The constructor (function) is a special function declared inside the class statement. This function (if it exist) is called when an object is created, all arguments from the class-name calling is passed to the constructor function. The constructor function supports all features of function calling (such as default arguments). The constructor is usually used to initialize object instance variables on the special `$this` variable.

```hsl
class Foo
{
        constructor($a, $b = 5) { $this->a = $a; }
}
$x = Foo(5);
```

> **Note**
> 
> There is no destructor. Objects are destructed (garbage collected) when they aren’t referenced by anyone.

<a id="instance"></a>

### Instance

An instance of a class is created by calling the name of the class (hence calling the constructor). This will create a special `$this` variable bound to the object. Property and method access is done with the [property access](operators.html.md#propertyoperator) operator (`->`) or [subscript](operators.html.md#subscript) operator (`[]`).

<a id="this"></a>

#### $this

The `$this` variable is a private instance variable that can only be used within a class function and is used to access the
instance methods and variables (private and public). This variable is iterable using the [foreach](#foreach) structure. If returned from a class function it will reference the public interface of the instance.

```hsl
class Foo
{
        $value = 0;

        // serialize data members...
        function serialize() {
                $data = [];
                foreach ($this as $k => $v)
                        if (!is_function($v))
                                $data[$k] = $v;
                return $data;
        }

        // unserialize data members
        function unserialize($data) {
                foreach ($data as $k => $v)
                        $this[$k] = $v;
                return $this;
        }
}

$x = Foo();
$x->value = 123;

$export = json_decode(json_encode($x->serialize()));

$y = Foo()->unserialize($export);
echo $y->value;
```

<a id="id18"></a>

#### variables

An instance variable is either defined in the class body or created on the `$this` object (variable) in the constructor function. At any time, new properites may be added and removed on the `$this` object.

```hsl
class Foo
{
        $y = 5;
        constructor() { $this->x = 5; }
}
$x = Foo();
echo $x->x;
echo $x->y;
```

<a id="id19"></a>

#### functions

A instance function is a function declared in a class statement and is only available on object instances. On execution it has access to the object’s `$this` variable.

```hsl
class Foo
{
        function setX() { $this->x = 5; }
}
$x = Foo();
echo $x->setX();
```

<a id="static"></a>

### Static

A static function or variable is not bound to a class instance instead they are only scoped by the class name using the [scope resolution](operators.html.md#scopeoperator) operator (`::`). Static members are not available on instance objects.

<a id="id20"></a>

#### variables

A static variable is declared within a class statement using the *static* keyword. A static variable is namespaced to the scope of the class name and it’s initialized at compile time (but can be updated and used at runtime). A static variable can only be initialized to a constant expressions which can be evaluated during compile-time.

```hsl
class Foo
{
        static $x = 10;
}
echo Foo::$x;
```

<a id="id21"></a>

#### functions

A static function is declared within a class statement using the *static* keyword. A static function is namespaced to the scope of the class name. On execution it does not has access to a `$this` variable. Instead to hold state, a static function usually use static class variables.

```hsl
class Foo
{
        static $x = 10;
        static function getX() { return Foo::$x; }
}
echo Foo::getX();
```

<a id="visibility"></a>

### Visibility

The default visibility of class members are public. However both instance- and static -variables and functions can be declared as private.

<a id="private"></a>

#### private

Variables and functions may be declared as private, in which case they can only be accessed from within other function on the same instance or class.

```hsl
class Foo
{
        function publicAPI() { $this->do(); }
        private function do() { }

        static function publicAPI2() { Foo::do2(); }
        private static function do2() { }
}
$x = Foo();
$x->publicAPI();
Foo::publicAPI2();
```

<a id="permissions"></a>

### Permissions

The default permissions of public class variable allows for read and write access.

<a id="readonly"></a>

#### readonly

Variables may be declared as readonly, in which case they can only be written to from within function on the same instance.

```hsl
class Foo
{
        readonly $count = 0;

        function inc() { $this->count += 1; }
}
$x = Foo();
$x->inc();
echo $x->count; // 1
$x->count = 2; // Error
```

<a id="cache"></a>

## cache

The *cache* statement can be prepended to any named function call. If the same call is done and the result is already in its cache the function will not be executed again, instead the previous result will be used. The cache take the function name and argument values into account when caching. In case of concurrent cache misses, the consecutive request will wait for the first to complete and use its result.

```default
cache [ cache-option [, cache-option [, ...]]] [builtin] funcname()
```

The following cache options are available.

> > * **ttl** (number, none) Time to Live (TTL) in seconds for the cache entry if added to the cache during the call. If *ttl* is `none` the cache will not expire based on time. The default time is `60` seconds.
> > * **ttl_override** (array) An associative array where the key is the *return value* and the value is the overridden *ttl* to be used.
> > * **ttl_function** (function) A function taking one argument (the function’s *return value*) and returning the *ttl* to be used.
> > * **update_function** (function) A function called at cache updates; taking two arguments (the *old* and *new* value) and returning the value to be used and cached. Using this function will disable the active TTL expiration (since it needs to keep the old value), the cache size will grow up to the size limit.
> > * **insert_function** (function) A function called at cache insert; taking one arguments (the *new* value) and returning the value to be used and cached.
> > * **miss_function** (function) If configured a function called at cache misses instead of the actual function, the returning the value will be the result of the call.
> > * **argv_filter** (array) A list of argument indexes (starting at 1) which should make this cache entry unique. The default is to use all arguments.
> > * **force** (boolean) Force a cache-miss. The default is `false`.
> > * **size** (number) The size of the cache (a cache is namespace + function-name). The default is `32`.
> > * **namespace** (string) Custom namespace so that multiple caches can be created per function name. The default is an empty string.
> > * **lru** (boolean) If the cache is full and a cache-miss occur it will remove the Least Recently Used (LRU) entry in order to be able to store the new entry. The default is `true`.
> 
> ```hsl
> // cache both the json_decode() and http() request
> function json_decode_and_http(...$args) {
>             return json_decode(http(...$args));
> }
> $list = cache [] json_decode_and_http("http://api.example.com/v1/get/list");
> ```

The  *\_function* arguments will be called in the following order.

* On initial cache call
  1. ttl_function
  2. insert_function
* On cache update
  1. ttl_function
  2. update_function

> **Warning**
> 
> Not all functions should be cached. If calls cannot be distinguished by their arguments or if they have side-effects (like Defer), bad things will happen.
> 
> ```hsl
> // Defer messages on Sundays
> if (cache [] strftime("%u") == "7")  // The same (and incorrect) day will be used for all days messages
>     cache [] Defer();                // if Sunday, Defer may still on happen once for one single message...
> Accept();                            // ...and all other messages will be delivered.
> ```

> **Note**
> 
> By default (if not distinguish by *namespace*), all cached calls to the same function name share the same cache bucket, consequently the cache statement with the smallest size set the effective max size for that cache. It’s recommended to use different *namespaces* for unrelated function calls.

> **Note**
> 
> The process cache scope (*scripting.cache.scope*) can either be *config* (cleared on configuration reload, default), or *global* (persistent).
> If the *ttl* is `none`, the cache will not expire and can only be cleared manually, this is useful for eg. doing one-time parsing of imported data on configuration reloads.

<a id="barrier"></a>

<a id="id22"></a>

## barrier

A *barrier* is *named* mutually exclusive scope, only one execution is allowed to enter the same named scope (applies to all thread). Waiters are queued for execution in random order. Optionally with every barrier comes a shared variable (*shared memory*) which data is shared among executions. Barries share the same memory and lock as the [memory](functions.html.md#shared-memory) functions.

```default
barrier statement {
        statements
}
barrier statement => variable {
        statements
}
```

```hsl
barrier "counter" => $var {
        $var = isset($var) ? $var : 0;
        echo $var;
        $var += 1;
}
```
