## Statements

Statements express how a process or function in a system works. They define what is done and in which order. Many statements use data for their decisions, which is stored in local variables. The combined local variables and statements are called 'body' with the following syntax.

Data values available to the process are the global constants (see Constant definitions) and enumeration values (see Enumeration definitions). The formal parameters of the surrounding process definition (explained in Process definitions) or the surrounding function definition (explained in Function definitions) are added as well.

Data storage that can be modified by the process are the local variables, defined by the `VarDefinitions` block in the `Body` diagram above (variable definitions are explained below in Local variables).

The data values and the modifiable data storage is used by the statements of the `Body` in the path after `1`. For ease of reference they are grouped by kind of statement as shown in the `Statement` diagram below.

- The `AssignmentStatement` is used to assign new values to the local variables (and explained further in Assignment statement).

- The `IterativeStatement` allows repeated execution of the same statements by means of the `for` and `while` statements (further explained in Iterative statements).

- The `ChoiceStatement` allows selection on which statement to perform next by means of the `if` statement (explained in Choice statement).

- The `run` and `start` statements of the `SubProcessStatement` group (explained in Sub-process statements) start new processes.

- Communication with other processes using channels is done with send, receive, and `select` statements in `CommunicationStatement` (explained in Communication statements)

- Finally, the `OtherStatements` group contains several different statements (explained further in Other statements). The more commonly used statements in that group are the `delay` statement, the `write` statement, and the `return` statement.

The syntax diagram of `Body` states that statements are separated from each other with a semicolon (`;`). The compiler allows more freedom. Semicolons may be omitted before and after a `end` keyword, and a semicolon may be added after the last statement.

### Local variables

Local variables are introduced in a process or function using the following syntax.

Variable definitions start with a `Type` node (its syntax if explained in Types), followed by a sequence of variable names where each variable may be initialized with a value by means of the `= Expression` path. If no value is assigned, the variable gets the default value of the type. Use a semicolon to terminate the sequence of new variables.

Next, another set of variables may be defined by going back to the start of the diagram, and giving another `Type` node, or the diagram can be ended, and the statements of the process or function can be given.

### Assignment statement

An assignment statement assigns one or more values to the local variables. Its syntax is as follows.

The assignment statement computes the value of every `Expression` at the right. If there is one expression, its value is also the value to assign. If there are more expressions, a tuple value is constructed, combining all values into one tuple (see Tuple expression for a discussion of tuple values).

At the left, a number of `Addressable` blocks define where the computed value is assigned to.

An `Addressable` is a variable. If the variable has a tuple type (see Tuple type) a field of the tuple may be assigned only using Path 1. Similarly, if the variable is a list (see List type) or a dictionary (see Dictionary type) assignment is done to one element by using Path 2. The `Expression` here is evaluated before any assignment by this statement is performed. Since selected elements may also have a type that allows selection, element selection can be repeated.

After processing the element selections at the left, it is known where values are assigned to. If there is exactly one addressable at the left, its type must match with the type of the value at the right (which may be a constructed tuple value as explained above). The value gets copied into the variable (or in its element if one is selected). If there are several addressable values at the left, the number of values must be equal to the length of the tuple from the expression(s) at the right, and each field of the right tuple must pair-wise match with the type of the addressed element at the left. In the latter case, all assignments are done at the same moment.

For a few examples, a number of variable declarations are needed:

    int x, y;
    real r;
    list(10) int xs;
    tuple(real v; int w) t;
    func tuple(real v; int w) (int) f;

    ...  # Initialization of the variables omitted

The variable declarations introduce integer variables `x` and `y`, a real number variable `r`, a list of 10 integers `xs`, a tuple `t` with two fields, and a function variable `f`.

For reasons of clarity, initialization of the variables has been omitted. Also, expressions at the right are simple values. However, you may use all allowed expression operations explained in the next chapter (Expressions) to obtain a value to assign. The first assignments show assignment of values to variables where there is one explicit value for every assigned variable:

    x = 3;
    t = f(y);
    x, y = 4, 5;
    xs[0], t.v = x+x, r;

The first assignment statement assigns 3 to `x`. The second assignment assigns the return value of the function call `f(y)` to tuple `t`. The third assignment assigns 4 to `x` and 5 to `y` at the same time. The fourth assignment assigns the value of `x+x` to the first element of the list `xs`, and the value of `r` to the `v` field of tuple `t`.

The next assignments show combining or splitting of tuples:

    t = r, y;
    r, x = t;
    r, x = f(y);

The first assignment assigns a new value to every field of tuple `t` (`t.v` gets the value of `r`, while `t.w` gets the value of `y`). This is called packing, it 'packs' the sequence of values into one tuple. The opposite operation is demonstrated in the second assignment. The value of each field of `t` is assigned to a separate variable. The types of the variables at the left have to pair-wise match with the field types of the tuple at the right. This assignment is called unpacking, it 'unpacks' a tuple value into its separate elements. The third assignment does the same as the second assignment, the difference is that the value at the right is obtained from a function call. The origin of the value is however irrelevant to the assignment statement.

To demonstrate the order of evaluation, the following assignment, under the assumption that variable `x` holds value 3:

    x, xs[x-1] = 7, x+2;

The assignment first computes all values at the right. Since there are more than one expression, they are combined into a tuple:

    x, xs[x-1] = (7, 5);

Next, the addressable values are calculated:

    x, xs[2] = (7, 5);

Finally the values are assigned, `x` gets a new value 7, while the third element of `xs` gets the value of expression `x+2`.

The expressions at the right as well as the expressions to select elements in lists and dictionaries are always evaluated using values from before the assignment.

It is forbidden to assign the same variable or selected element more than once:

    x, x = 3, 3         # Error, assigned 'x' twice.
    xs[0], xs[1] = 0, 1 # Allowed, different selected elements.
    xs[0], xs[x] = 0, 1 # Allowed if x != 0.

### Iterative statements

The iterative statements are shown below.

The Chi language has two statements for repeatedly executing a body (a sequence of statements), a `while` statement and a `for` statement. The former is the generic iterative statement, the latter simplifies the common case of iterating over a collection of values.

The `break` and `continue` statements change the flow of control in the iterative statements.

#### While loop statement

A while loop starts with the keyword `while` with a boolean condition. Between the colon and the `end` keyword, the body of statements is given, which is executed repeatedly.

Executing an iterative `while` statement starts with evaluating the boolean condition. If it does not hold, the `while` statement ends (and execution continues with the statement following the while statement). If the condition holds, the statements in the body are executed from start to end (unless a `break` or `continue` statement is executed, as explained below). After the last statement has been executed, the `while` statement starts again from the beginning, by evaluating the boolean condition again.

As an example, consider the following code:

    int s, i;

    while i < 10:
        s = s + i
        i = i + 1
    end

At first, the `i < 10` condition holds, and the body of the `while` statement (two assignment statements) is executed. After the body has finished, `i` has been incremented, but is still less than `10`. The condition again holds, and the body is again executed, etc. This process continues, until the final statement of the body increments `i` to `10`. The condition does not hold, and execution of the `while` statement ends.

#### For loop statement

A common case for iterating is to execute some statements for every value in a collection, for example a list:

    list int xs;
    int x;
    int i;

    while i < size(xs):
        x = xs[i]
        ...
        i = i + 1
    end

where the `...` line represents the statements that should be executed for each value `x` of the list. This is a very common case. Chi has a special statement for it, the `for` statement. It looks like:

    list int xs;

    for x in xs:
        ...
    end

This code performs the same operation, the statements represented with `...` are executed for each value `x` from list `xs`, but it is shorter and easier to write. The advantages are mainly a reduction in the amount of code that must be written.

- No need to create and update the temporary index variable `i`.

- Variable `x` is declared implicitly, no need to write a full variable declaration for it.

The behavior is slightly different in some circumstances.

- There is no index variable `i` that can be accessed afterwards.

- When the `...` statements modify the source variable (`xs` in the example), the `while` statement above uses the changed value. The `for` statement continues to use the original value of the source variable.

Continuing use of the original source value can be an advantage or a disadvantage, depending on the case. Using the new value gives more flexibility, keeping the old value makes the `for` statement more predictable, for example indices in the source variable stay valid.

Besides iterating over a list with `for`, you can also iterate over element values of a set, or over key-value tuples of a dictionary, for example:

    dict(int:int) d = {1:10, 2:20};

    for k, v in d:
        writeln("%s: %s", k, v);
    end

When iterating over a set or a dictionary, the order of the elements is undefined. In the above example, the first pair is either `(1, 10)` or `(2, 20)`.

#### Break statement

The `break` statement may only be used inside the body of a loop statement. When executed, the inner-most loop statement ends immediately, and execution continues with the first statement after the inner-most loop statement. An example:

    # Get a slice of the xs list, up-to the position of value x in the list
    func get_until(list int xs, int x):
        int index;

        while index < size(xs):
            if xs[index] == x:
                break
            end;
            index = index + 1
        end
        return xs[:index]
    end

In the example, elements of the list `xs` are inspected until an element with a value equal to `x` is found. At that point, the loop ends with the `break` statement, and the function returns a slice of the list.

#### Continue statement

Another common case when executing the body of an inner-most loop is that the remaining statements of the body should be skipped this time. It can be expressed with an `if` statement, but a `continue` statement is often easier.

The syntax of the continue statement is just `continue`. An example to demonstrate its operation:

    int s;

    for x in xs:
        if x mod 5 == 0:
            continue
        end
        s = s + x
    end

The `for` statement iterates over every value in list `xs`. When the value is a multiple of 5 (expressed by the condition `x mod 5 == 0`), the `continue` is executed, which skips the remaining statements of the body of the `for` statement, namely the `s = s + x` assignment. The result is that after executing the `for` statement, variable `s` contains the sum of all values of the list that are not a multiple of 5.

### Choice statement

The choice statement, also known as 'if statement', selects one alternative from a list based on the current value of a boolean expression. The alternatives are tried in turn, until a boolean expression one an alternative yields true. The statements of that alternative are executed, and the choice statement ends. The choice statement also ends when all boolean expressions yield false. The boolean expression of the `else` alternative always holds.

The syntax of the choice statement is as follows.

Processing starts with evaluating the `BooleanExpression` behind the `if`. If it evaluates to `true`, the statements behind it are executed, and the choice statement ends.

If the boolean expression behind the `if` does not hold, the sequence `elif` alternatives is tried. Starting from the first one, each boolean expression is evaluated. If it holds, the statements of that alternative are performed, and the choice statement ends. If the boolean expression does not hold, the next `elif` alternative is tried.

When there are no `elif` alternatives or when all boolean expressions of the `elif` alternatives do not hold, and there is an `else` alternative, the statements behind the `else` are executed and the choice statement ends. If there is no `else` alternative, the choice statement ends without choosing any alternative.

An example with just one alternative:

    if x == 1:
        x = 2
    end

which tests for `x == 1`. If it holds, `x = 2` is performed, else no alternative is chosen.

An longer example with several alternatives:

    if x == 1:
         y = 5
    elif x == 2:
        y = 6; x = 6
    else:
        y = 7
    end

This choice statement first tests whether `x` is equal to `1`. If it is, the `y = 5` statement is executed, and the choice statement finishes. If the first test fails, the test `x == 2` is computed. If it holds, the statements `y = 6; x = 6` are performed, and the choice statement ends. If the second test also fails, the `y = 7` statement is performed.

The essential points of this statement are:

- The choice is computed now, you cannot wait for a condition to become true.

- Each alternative is tried from the top down, until the first expression that yields true.

The second point also implies that for an alternative to be chosen, the boolean expressions of all previous alternatives have to yield false.

In the above example, while executing the `y = 7` alternative, you know that `x` is neither `1` nor `2`.

### Sub-process statements

The sub-process statements deal with creating and managing of new processes. The statement may only be used in Process definitions and Model definitions.

The `RunStartStatement` block creates new processes (see Run and start statements for details), while the `FinishStatement` waits for a process to end (further explanation at Finish statement).

#### Run and start statements

The `run` and `start` commands take a sequence of process instance as their argument.

Both statements start all instances listed in the sequence. The `start` statement ends directly after starting the processes, while the `run` statement waits until all the started instances have ended. Using `run` is generally recommended for creating new processes.

A process instance has the following syntax.

The elementary process instance is created using Path 1. It consists of a process name (which must be one of the names of the Process definitions), followed by a sequence of actual parameters for the process between parentheses. The number of actual parameters and their types must match pair-wise with the number and type of the formal parameters of the referenced process definition. Channel directions of the formal parameters must be a sub-set of the channel directions of the actual parameters.

The optional assignment of the process to a process variable (which must be of type `inst`, see Instance type) allows for checking whether the started process has ended, or for waiting on that condition in a `select` statement (explained in Select statement), or with a `finish` statement (explained in Finish statement).

For example:

    chan c;
    inst p, q;

    run P(18, c), Q(19, c);
    start p = P(18, c), q = Q(19, c);

First two processes are completely run, namely the instances `P(18, c)`, and `Q(19, c)`. When both have ended, the `start` statement is executed, which starts the same processes, and assigned the `P` process instance to instance variable `p` and the `Q` process instance to variable `q`. After starting the processes, the `start` ends. Unless one of started processes has already ended, in the statement following the `start`, three processes are running, namely the process that executed the start statement, and the two started process instances referenced by variables `p` and `q`. (There may be more processes of course, created either before the above statements were executed, or the `P` or `Q` process may have created more processes.)

Path 2 of the `ProcessInstance` diagram is used to construct many new processes by means of an `unwind` loop. Each value in the `Expression` gets assigned to the iterator variable sequence of `VariableName` blocks (and this may be done several times as the syntax supports several `Expression` loops). For each combination of assignments, the process instances behind the colon are created. The `end` keyword denotes the end of the `unwind`.

Typical use of `unwind` is to start many similar processes, for example:

    list int xs = [1, 2]

    run
        unwind i in range(5),
               j in range(3),
               x in xs: P(i, j, x)
        end;

This `run` statement runs 5*3*2 processes: `P(0, 0, 1)`, `P(0, 0, 2)`, `P(0, 1, 1)`, …​, `P(0, 2, 2)`, `P(1, 0, 1)`, …​, `P(4, 2, 2)`.

Both the `run` and the `start` statements can always instantiate new processes that have no exit type specified. (see Process definitions for details about exit types in process definitions). If the definition containing the sub-process statement has an exit type, the statements can also instantiate processes with the same exit type.

This requirement ensures that all exit statements in a model simulation give exit values of the same type.

#### Finish statement

The `finish` statement allows waiting for the end of a process instance. The statement may only be used in Process definitions and Model definitions. Its syntax is as follows.

Each process variable must be of type `inst` (see Instance type for details). The statement ends when all referenced process instances have ended. For example:

    chan bool c;
    inst p, q;

    start p = P(18, c), q = Q(19, c);
    finish p, q;

During the `start` statement (see Run and start statements), instance variables `p` and `q` get a process instance assigned (this may also happen in different `start` statements). The `finish` statement waits until both process instances have ended.

### Communication statements

Communication with another process is the only means to forward information from one process to another processes, making it the primary means to create co-operating processes in the modeled system. The statement may only be used in Process definitions and Model definitions.

All communication is point-to-point (from one sender to one receiver) and synchronous (send and receive occur together). A communication often exchanges a message (a value), but communication without exchange of data is also possible (like waving 'hi' to someone else, the information being sent is 'I am here', but that information is already implied by the communication itself). The latter form of communication is called synchronization.

Send and receive does not specify the remote process directly, instead a channel is used (see Channel type and Channel expressions sections for more informations about channels and how to create them). Using a channel increases flexibility, the same channel can be used by several processes (allowing communication with one of them). Channels can also be created and exchanged during execution, for even more flexibility.

Setting up a communication channel between two processes is often done in the following way:

    chan void sync;   # Synchronization channel
    chan int  dch;    # Channel with integer number messages

    run P(sync, dch), Q(sync, dch);

In a parent process, two channels are created, a synchronization channel `sync`, and a communication channel with data called `dch`. The channel values are given to processes `P` and `Q` through their formal parameters.

The communication statements are as follows.

The elementary communication statements for sending and receiving at a single channel are the Send statement and the Receive statement. The Select statement is used for monitoring several channels and conditions at the same time, until at least one of them becomes available.

#### Send statement

The send statement send signals or data away through a channel. The statement may only be used in Process definitions and Model definitions. It has the following syntax:

The statement takes a channel value (derived from `ChannelExpression`), and waits until another process can receive on the same channel. When that happens, and the channel is a synchronization channel, a signal 'Communication has occurred' is being sent, if the channel also carries data, the `Expression` value is computed and sent to the other process. For example:

    proc P(chan void a, chan! int b):
        a!;
        b!21;
    end

Process `P` takes two parameters, a synchronization channel locally called `a` and a outgoing channel called `b` carrying integer values. In the process body, it first synchronizes over the channel stored in `a`, and then sends the value `21` of the channel stored in `b`.

#### Receive statement

The receive statement receives signals or data from a channel. The statement may only be used in Process definitions and Model definitions. It has the following syntax:

The statement takes a channel value (derived from the `ChannelExpression`), and waits until another process can send on the same channel. For synchronization channels, it receives just a signal that the communication has occurred, for channels carrying data, the data value is received and stored in the variable indicated by `Addressable`. For example:

    proc Q(chan void a, chan int b):
        int x;

        a?;
        b?x;
        writeln("%s", x);
    end

Process `Q` takes a synchronization channel called `a` and a data channel for integer values called `b` as parameters. The process first waits for a synchronization over channel `a`, and then waits for receiving an integer value over channel `b` which is stored in local variable `x`.

#### Select statement

The Send statement and the Receive statement wait for communication over a single channel. In some cases, it is unknown which channel will be ready first. Additionally, there may be time-dependent internal activities that must be monitored as well. The select statement is the general purpose solution for such cases. The statement may only be used in Process definitions and Model definitions.

It has the following syntax:

The statement has one or more `SelectCondition` alternatives that are all monitored. The first alternative is prefixed with `select` to denote it is a the start of a select statement, the other alternatives each start with `alt` (which is an abbreviation of 'alternative').

The statement monitors all conditions simultaneously, waiting for at least one to become possible. At that moment, one of the conditions is selected to be executed, and the select statement ends.

The syntax of a `SelectCondition` is:

In its simplest form, a `SelectCondition` is a `SelectAlternative` (taking Path 1). At Path 2, the condition is eventually also an `SelectAlternative`, but prefixed with an `unwind` construct, and with an additional `end` keyword at the end to terminate the unwind.

The unwind construct allows for a compact notation of a large number of alternatives that must be monitored. Examples are provided below.

Using Path 1, a `SelectAlternative` can be a Send statement or a Receive statement, which may optionally have a `BooleanExpression` condition prefix. Path 2 allows for a condition without a send or receive statement.

The alternative checks the condition and monitors the channel. If the condition holds and the channel has a communication partner, the alternative can be chosen by the select statement. (Of course, omitting a condition skips the check, and not specifying a send or receive statement skips monitoring of the channel.) When an alternative is chosen by the select statement, the send or receive statement are performed (if it was present). If additional statements were given in the alternative using Path 3, they are executed after the communication has occurred (if a send or receive was present).

A few examples to demonstrate use of the select statement:

    timer t = timer(5.2);

    select
        a?
    alt
        b!7:
            writeln("7 sent")
    alt
        ready(t):
            writeln("done")
    end

This select waits until it can receive a signal from channel `a`, it can send value `7` over channel `b`, or until `ready(t)` holds (which happens `5.2` time units after starting the `select`, see Timers for details). If `b!7` was selected, the `writeln("7 sent")` is executed after the communication over channel `b`. If the `ready(t)` alternative is chosen, the `writeln("done")` is executed.

A buffer can be specified with:

    list int xs;
    int x;

    select
        a?x:
            xs = xs + [x]
    alt
        not empty(xs), b!xs[0]:
            xs = xs[1:]
    end

The select either receives a value through channel `a`, or it sends the first element of list `xs` over channel `b` if the list is not empty (the condition must hold and the channel must be able to send an item at the same time to select the second alternative).

After communication has been performed, the first alternative appends the newly received value `x` to the list (the received value is stored in `x` before the assignment is executed). In the second alternative, the assignment statement drops the first element of the list (which just got sent away over channel `b`).

The `unwind` loop 'unwinds' alternatives, for example:

    list(5) chan int cs;
    int x;

    select
        unwind i, c in enumerate(cs):
            c?x:
                writeln("Received %s from channel number %d", x, i)
        end
    end

Here `cs` is a list of channels, for example `list(5) chan int cs`. (See List type for details about lists.) The `unwind` iterates over the `enumerate(cs)` (see List expressions for details about `enumerate`), assigning the index and the channel to local `i` and `c` variables. The `SelectAlternative` uses the variables to express the actions to perform (wait for a receive, and output some text saying that a value has been received).

The above is equivalent to (if list `cs` has length 5):

    select
        cs[0]?x:
            writeln("Received %s from channel number %d", x, 0)
    alt
        cs[1]?x:
            writeln("Received %s from channel number %d", x, 1)

    ...

    alt
        cs[4]?x:
            writeln("Received %s from channel number %d", x, 4)

The `unwind` however works for any length of list `cs`. In addition, the `unwind` allows for nested loops to unfold for example `list list bool ds`, or to send one of several values over one of several channels.

### Other statements

Finally, there are a number of other useful statements.

The Delay statement waits for the given amount of time units, the Write statement outputs text to the screen or a file, the Close statement closes a file, the Return statement returns a value from a function. the Exit statement ends the execution of all processes, and the Pass statement does nothing.

#### Delay statement

The `delay` statement is useful to wait some time. The statement may only be used in Process definitions and Model definitions. It has the following syntax:

The `IntegerExpression` or `RealExpression` is evaluated, and is the amount of time that the statement waits. The value of the expression is computed only at the start, it is not evaluated while waiting. Changes in its value has thus no effect. A negative value ends the statement immediately, you cannot go back in time.

Examples:

    delay 1.5   # Delay for 1.5 time units.

#### Write statement

The write statement is used to output text to the screen or to a file. It has the following syntax:

The format string at 2 is a literal string value (further explained at String expressions) which defines what gets written. Its text is copied to the output, except for two types of patterns which are replaced before being copied. Use of the `writeln` (write line) keyword causes an additional `\n` to be written afterwards.

The first group of pattern are the back-slash patterns. They all start with the `\` character, followed by another character that defines the character written to the output. The back-slash patterns are listed in the table below.

Pattern | Replaced by
--- | ---
`\n` | The new-line character (U+000A)
`\t` | The tab character (U+0009)
`\"` | The double-quote character (U+0022)
`\\` | The back-slash character (U+005C)

The second group of patterns are the percent patterns. Each percent pattern starts with a `%` character. It is (normally) replaced by the (formatted) value of a corresponding expression listed after the format string (the first expression is used as replacement for the first percent pattern, the second expression for the second pattern, etc). How the value is formatted depends on the format specifier, the first letter after the percent character. Between the percent character and the format specifier may be a format definition giving control on how the value is output.

The format definition consists of five parts, each part is optional.

- A `-` character, denoting alignment of the value to the left. Cannot be combined with a `0`, and needs a width.

- A `+` character, denoting the value with always be printed with a sign, only for formatting decimal integers, and real numbers.

- A `0` character, denoting the value will be prefixed with zeros, only for integer numbers. Cannot be combined with `-`, and needs a width.

- A width as decimal number, denoting the minimal amount of space used for the value. The value will be padded with space (or zeros if the `0` part has been specified).

- A `.` and a precision as decimal number, denoting the number of digits to use for the fraction, only for real numbers.

The format definition is a single letter, the table below lists them and their function.

Definition | Description
--- | ---
`b` | Output boolean value.
`d` | Output integer value as decimal number.
`x`, `X` | Output integer value as hexadecimal number.
`f` | Output real value as number with a fraction.
`e`, `E` | Output real value in exponential notation.
`g`, `G` | Output real value either as `f` or as `e` (`E`) depending on the value
`s` | Output value as a string (works for every printable value)
`%` | Output a `%` character

#### Close statement

The `close` statement takes a value of type `file` as argument (see File type for details about the file type). It closes the given file, which means that the file is no longer available for read or write. In case data was previously written to the file, the `close` statement ensures that the data ends up in the file itself.

Note that a close of a file is global in the system, none of the processes can use the file any longer.

In Reading from a file and Writing to a file, use of the close statement is shown.

#### Return statement

The return statement may only be used in a Function definitions. It has the following syntax:

The statement starts with a `return` keyword, followed by one or more (comma-separated) expressions that form the value to return to the caller of the function.

The value of the expressions are calculated, and combined to a single return value. The type of the value must match with the return type of the function. Execution of the function statements stops (even when inside a loop or in an alternative of an `if` statement), and the computed value is returned to the caller of the function.

Examples:

    return 4          # Return integer value 4 to the caller.

    return true, 3.7  # Return value of type tuple(bool b; real r).

#### Exit statement

The `exit` statement may only be used in Process definitions and Model definitions. It has the following syntax:

The exit statement allows for immediately stopping the current model simulation. The statement may be used in Process definitions and Model definitions. If arguments are provided, they become the exit value of the model simulation. Such values can be processed further in an Simulating several scenarios, see also Experiment definitions on how to run a model in an experiment.

The type of the combined arguments must match with the exit type of the process or model that uses the statement. If no arguments are given, the exit type must be a `void` type (see also Void type).

If an experiment is running, execution continues by returning from the model instantiation call. Otherwise, the simulation as a whole is terminated.

#### Pass statement

The `pass` statement does nothing. Its purpose is to act as a place holder for a statement at a point where there is nothing useful to do (for example to make an empty process), or to explicitly state nothing is being done at some point:

    if x == 3:
        pass
    else:
        x = x + 1
    end

Here, `pass` is used to explicitly state that nothing is done when `x == 3`. Such cases are often a matter of style, usually it is possible to rewrite the code and eliminate the `pass` statement.