## Expressions

Expressions are computations to obtain a value. The generic syntax of an expression is shown below.

- As shown in Path 1, a name may be used in an expression. It must refer to a value that can be used in an expression. Names are explained further at Names.

  The first four entries are quite normal, function names can be used for variables with a function type (see Function type) and process names for variables with a process type (see Process type). The latter two are mainly useful as actual parameters of functions or processes.

- Path 2 states that you can write parentheses around an expression. Its main use is to force a different order of applying the unary and binary operators (see Operator priorities). Parentheses may also be used to clarify the meaning of a complicated expression.

- Path 3 gives access to the other parts of expressions. Typed expressions gives the details about typed expressions.

### Typed expressions

The number of operators in expressions is quite large. Also, each node has an associated type, and the allowed operators depend heavily on the types of the sub-expressions. To make expressions easier to access, they have been split. If possible the (result) type is leading, but in some cases (like the `ReadExpression` for example) this is not feasible.

- The expressions with a boolean type are denoted by the `BooleanExpression` block and explained further in Boolean expressions.

- The expressions with an integer type are denoted by the `IntegerExpression` block and explained further in Integer expressions.

- The expressions with a real number type are denoted by the `RealExpression` block and explained further in Real number expressions.

- The expressions with a string type are denoted by the `StringExpression` block and explained further in String expressions.

- The expressions with a list type are denoted by the `ListExpression` block and explained further in String expressions.

- The expressions with a set type are denoted by the `SetExpression` block and explained further in Set expressions.

- The expressions with a dictionary type are denoted by the `DictionaryExpression` block and explained further in Dictionary expressions.

- The expressions with a tuple type are denoted by the `TupleExpression` block and explained further in Tuple expression.

- The expressions with a file handle type are denoted by the `FileExpression` block and explained further in File handle expressions.

- The function to read values from an external source is shown in the `ReadExpression` block, and further discussed in Read expression.

- The expressions with a timer type are denoted by the `TimerExpression` block and explained further in Timer expressions.

- The expressions with a channel type are denoted by the `ChannelExpression` block and explained further in Channel expressions.

- The expressions with a distribution type are denoted by the `DistributionExpression` block and explained further in Distribution expressions.

- The expressions with a process type are denoted by the `ProcessExpression` block and explained further in Process expressions.

- The expressions with an instance type are denoted by the `InstanceExpression` block and explained further in Instance expressions.

- The expressions that convert one type to another are denoted by the `CastExpression` block, and explained further in Cast expressions.

- The expressions that perform a function call are denoted by the `FunctionCallExpression` block, and explained further in Function call expressions.

### Enumeration value

Enumeration values may be used as literal value in an expression.

See Enumeration definitions for a discussion about enumeration definitions and enumeration values.

There are two binary operators for enumeration values.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `==` rhs | E | E | bool | Test for equality
lhs `!=` rhs | E | E | bool | Test for inequality

Two enumeration values from the same enumeration definition E can be compared against each other for equality (or in-equality). Example:

    enum FlagColours  = {red, white, blue};

    ...

    bool same = (red == white);

### Boolean expressions

The literal values for the boolean data type are as follows.

The values `true` and `false` are also the only available values of the boolean data type.

The `not` operation is the only boolean unary operator.

Expression | Type op | Type result | Explanation
--- | --- | --- | ---
`not` op | bool | bool | op value is inverted.

The `and`, the `or`, and the equality tests are available for boolean values.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `and` rhs | bool | bool | bool | Both operands hold
lhs `or` rhs | bool | bool | bool | At least one operand holds
lhs `==` rhs | bool | bool | bool | Test for equality
lhs `!=` rhs | bool | bool | bool | Test for inequality

### Integer expressions

The syntax of an integer literal number is (at character level) as follows.

| This diagram works at lexical level (at the level of single characters), white space or comments are not allowed between elements in this diagram.

An integer number is either `0`, or a sequence of decimal digits, starting with a non-zero digit.

There are two unary operators on integer numbers.

Expression | Type op | Type result | Explanation
--- | --- | --- | ---
`-` op | int | int | op value is negated.
`+` op | int | int | op value is copied.

With the unary `-` operation, the sign of the operand gets toggled. The `+` unary operation simply copies its argument.

There are many binary operations for integer numbers, see the table below.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `+` rhs | int | int | int | Integer addition
lhs `-` rhs | int | int | int | Integer subtraction
lhs `*` rhs | int | int | int | Integer multiplication
lhs `/` rhs | int | int | real | Real division
lhs `div` rhs | int | int | int | Integer divide operation
lhs `mod` rhs | int | int | int | Modulo operation
lhs `^` rhs | int | int | real | Power operation
lhs `<` rhs | int | int | bool | Test for less than
lhs `<=` rhs | int | int | bool | Test for less or equal
lhs `==` rhs | int | int | bool | Test for equality
lhs `!=` rhs | int | int | bool | Test for inequality
lhs `>=` rhs | int | int | bool | Test for bigger or equal
lhs `>` rhs | int | int | bool | Test for bigger than

The divide operator `/` and the power operator `^` always gives a real result, integer division is performed with `div`. The operation always rounds down, that is a `div` b == `floor`(a `/` b) for all integer values a and b. The `mod` operation returns the remainder from the `div`, that is a `mod` b == a - b * (a `div` b). The table below gives examples. For clarity, the sign of the numbers is explicitly added everywhere.

Example | Result | Explanation
--- | --- | ---
`+7 div +4` | +1 | `floor(+7/+4) = floor(+1.75) = +1`
`+7 mod +4` | +3 | `+7 - +4 * (+7 div +4) = +7 - +4 * +1 = +7 - +4 = +3`
`+7 div -4` | -2 | `floor(+7/-4) = floor(-1.75) = -2`
`+7 mod -4` | -1 | `+7 - -4 * (+7 div -4) = +7 - -4 * -2 = +7 - +8 = -1`
`-7 div +4` | -2 | `floor(-7/+4) = floor(-1.75) = -2`
`-7 mod +4` | +1 | `-7 - +4 * (-7 div +4) = -7 - +4 * -2 = -7 - -8 = +1`
`-7 div -4` | +1 | `floor(-7/-4) = floor(+1.75) = +1`
`-7 mod -4` | -3 | `-7 - -4 * (-7 div -4) = -7 - -4 * +1 = -7 - -4 = -3`

The Chi simulator uses 32 bit integer variables, which means that only values from -2,147,483,647 to 2,147,483,647 (with an inclusive upper bound) can be used. Using a value outside the valid range will yield invalid results. Sometimes such values are detected and reported.

| The technical minimum value for integers is -2,147,483,648, but this number cannot be entered as literal value due to parser limitations.

### Real number expressions

Real numbers are an important means to express values in the contiguous domain. The type of a real number expression is a `real` type, see Real type for more information about the type. The syntax of real number values is as follows.

There are two ways to construct real numbers, by writing a literal real number, or by using `time` which returns the current time in the model.

The syntax of a literal real number (at character level) is as follows.

| This diagram works at lexical level (at the level of single characters), white space or comments are not allowed between elements in this diagram.

A literal real number starts with one or more digits, and then either a dot or an exponent. In the former case, an exponent is allowed as well. Examples:

    3.14
    0.314e1
    314E-2

A real number always has either a dot character, or an exponent notation in the number.

Many of the integer operations can also be performed on real numbers. The unary operators are the same, except for the type of the argument.

Expression | Type op | Type result | Explanation
--- | --- | --- | ---
`-` op | real | real | op value is negated.
`+` op | real | real | op value is copied.

With the unary `-` operation, the sign of the operand gets toggled. The `+` unary operation simply copies its argument.

The binary operators on real numbers is almost the same as the binary operators on integer numbers. Only the `div` and `mod` operations are not here.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `+` rhs | int,real | int,real | real | Addition
lhs `-` rhs | int,real | int,real | real | Subtraction
lhs `*` rhs | int,real | int,real | real | Multiplication
lhs `/` rhs | int,real | int,real | real | Real division
lhs `^` rhs | int,real | int,real | real | Power operation
lhs `<` rhs | int,real | int,real | bool | Test for less than
lhs `<=` rhs | int,real | int,real | bool | Test for less or equal
lhs `==` rhs | int,real | int,real | bool | Test for equality
lhs `!=` rhs | int,real | int,real | bool | Test for inequality
lhs `>=` rhs | int,real | int,real | bool | Test for bigger or equal
lhs `>` rhs | int,real | int,real | bool | Test for bigger than

With these operations, one of the operands has to be a real number value, while the other operand can be either an integer value or a real number value.

The standard library functions for real numbers contain a lot of math functions. They can be found in Real number functions.

The Chi simulator uses 64-bit IEEE 754 floating point numbers to represent real number values. Using a value outside the valid range of this format will yield invalid results. Sometimes such values are detected and reported.

### String expressions

Strings are sequences of characters. Their most frequent use is to construct text to output to the screen. A string literal is defined as follows.

| This diagram works at lexical level (at the level of single characters), white space or comments are not allowed between elements in this diagram.

A string literal starts with a quote character `"`, and ends with another quote character. In between, you may have a sequence of characters. Most characters can be written literally (eg write a `a` to get an 'a' in the string). The exceptions are a backslash `\`, a quote `"`, a TAB, and a NL (newline) character. For those characters, write a backslash, followed by `\`, `"`, `t`, or `n` respectively. (A TAB character moves the cursor to the next multiple of 8 positions at a line, a NL moves the cursor to the start of the next line.)

Strings have the following binary expressions.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `+` rhs | string | string | string | Concatenation
lhs `[` rhs `]` | string | int | string | Element access
lhs `[` low `:` high `]` | string | int, int | string | Slicing with step `1`
lhs `[` low `:` high `:` step `]` | string | int, int, int | string | Slicing
lhs `<` rhs | string | string | bool | Test for less than
lhs `<=` rhs | string | string | bool | Test for less or equal
lhs `==` rhs | string | string | bool | Test for equality
lhs `!=` rhs | string | string | bool | Test for inequality
lhs `>=` rhs | string | string | bool | Test for bigger or equal
lhs `>` rhs | string | string | bool | Test for bigger than

The concatenation operator joins two strings (`"a" + "bc"` gives `"abc"`).

The element access and slicing operators use numeric indices to denote a character in the string. First character has index value `0`, second character has index `1`, and so on. Negative indices count from the back of the string, for example index value `-1` points to the last character of a string. Unlike lists, both the element access and the slicing operators return a string. The former constructs a string with only the indicated character, while the latter constructs a sub-string where the first character is at index low, the second character at index low + step, and so on, until index value high is reached or crossed. That final character is not included in the result (that it, the high boundary is excluded from the result). If low is omitted, it is 0, if high is omitted, it is the length of the string (`size(` lhs `)`). If step is omitted, it is `1`. A few examples:

    string s = "abcdef";

    s[4]        # results in "e"
    s[2:4]      # results in "cd"
    s[1::2]     # results in "bdf"
    s[-1:0:-2]  # results in "fdb"
    s[-1:-7:-1] # results in "fedcba"
    s[:4]       # results in "abcd"
    s[-1:]      # results in "f" (from the last character to the end)

In the comparison operations, strings use lexicographical order.

There are also a few standard library functions on strings, see String functions for details.

Note that length of the string is not the same as the number of characters needed for writing the string literal, as shown in the following example.

    size("a")  # results in 1, string is 1 character long (namely 'a').
    size("\n") # results in 1, string contains one NL character.

### List expressions

Lists are very versatile data structures, the Chi language has a large number of operations and functions for them.

The most elementary list expression is a literal list. It has the following syntax.

The first line shows the syntax of an empty list. The `Type` block denotes the element type of the list, for example `<int>[]` is an empty list of integer values.

The second line shows how to write a non-empty literal list value. It is a comma-separated sequence of expressions surrounded by square brackets. The type of all expressions must be the same, and this is also the element type of the list.

Some examples:

    list int xs;
    list int ys = <int>[];
    list int zs = [1, 4, 28];

Variable `ys` is assigned an empty list with integer element type. Since an empty list is the default value of a variable, `xs` has the same value. Variable `zs` is initialized with a list holding three elements.

Two list values are equal when they have the same number of element values, and each value is pair-wise equal.

Lists have no unary operators, the binary operators of lists are shown below.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `[` rhs `]` | list T | int | T | Element access
lhs `[` low `:` high `]` | list T | int, int | list T | Slicing with step `1`
lhs `[` low `:` high `:` step `]` | list T | int, int, int | list T | Slicing
lhs `+` rhs | list T | list T | list T | Concatenation
lhs `-` rhs | list T | list T | list T | List subtraction
lhs `==` rhs | list T | list T | bool | Test for equality
lhs `!=` rhs | list T | list T | bool | Test for inequality
lhs `in` rhs | T | list T | bool | Element test

The element access operator 'lhs `[` rhs `]` ' indexes with zero-based positions, for example `xs[0]` retrieves the first element value, `xs[1]` retrieves the second value, etc. Negative indices count from the back of the list, `xs[-1]` retrieves the last element of the list (that is, `xs[size(xs)-1]`), `xs[-2]` gets the second to last element, ect. It is not allowed to index positions that do not exist. Examples:

    list int xs = [4, 7, 18];
    int x;

    x = xs[0];  # assigns 4
    x = xs[2];  # assigns 18
    x = xs[-1]; # assigns 18
    x = xs[-2]; # assigns 7

    xs[2]  # ERROR, OUT OF BOUNDS
    xs[-4] # ERROR, OUT OF BOUNDS

The slicing operator 'lhs `[` low `:` high `]` ' extracts (sub-)lists from the lhs source. The low and high index expressions may be omitted (and default to `0` respectively `size(` lhs `)` in that case). As with element access, negative indices count from the back of the list. The result is the list of values starting at index low, and up to but not including the index high. If the low value is higher or equal to high, the resulting list is empty. For example:

    list int xs = [4, 7, 18];
    list int ys;

    ys = xs[0:2];  # assigns [4, 7]
    ys = xs[:2];   # == xs[0:2]
    ys = xs[1:];   # == xs[1:3], assigns [7, 18]
    ys = xs[:];    # == xs[0:3] == xs

    ys = xs[1:2];  # assigns [7] (note, it is a list!)
    ys = xs[0:0];  # assigns <int>[]
    ys = xs[2:1];  # assigns <int>[], lower bound too high
    ys = xs[0:-1]; # == xs[0:2]

The slicing operator with the step expression (that is, the expression with the form 'lhs `[` low `:` high `:` step `]` ') can also skip elements (with step values other than `1`) and traverse lists from back to front (with negative step values). Omitting the step expression or using `0` as its value, uses the step value `1`. This extended form does not count from the back of the list for negative indices, since the high value may need to be negative with a negative step size.

The first element of the result is at 'lhs [low ]'. The second element is at 'lhs [low + step ]', the third element at 'lhs [low + 2 * step ]' and so on. For a positive step value, the index of the last element is the highest value less than high, for a negative step value, the last element is the smallest index bigger than high (that is, boundary high is excluded from the result). The (sub-)list is empty when the first value ('lhs [ low ]') already violates the conditions of the high boundary.

Examples:

    list int xs = [4, 7, 18];
    list int ys;

    ys = xs[::2];  # == xs[0:3:2], assigns [4, 18]
    ys = xs[::-1]; # == xs[2:-1:-1], assigns [18, 7, 4]

With the latter example, note that the `-1` end value in `xs[2:-1:-1]` really means index `-1`, it is not rewritten!

The concatenation operator `+` 'glues' two lists together by constructing a new list, copying the value of the lhs list, and appending the values of the rhs:

    [1, 2] + [3, 4] == [1, 2, 3, 4]
    <int>[] + [1]   == [1]
    [5] + <int>[]   == [5]

The subtraction operator `-` subtracts two lists. It copies the lhs list, and each element in the rhs list is searched in the copy, and the left-most equal value is deleted. Searched values that do not exist are silently ignored. The result of the operation has the same type as the lhs list. Some examples:

    [1, 2, 4, 2] - [4]        # results in [1, 2, 2], 4 is removed.
    [1, 2, 4, 2] - [6]        # results in [1, 2, 4 2], 6 does not exist.
    [1, 2, 4, 2] - [1, 4]     # results in [2, 2], 1 and 4 are removed.
    [1, 2, 4, 2] - [2]        # results in [1, 4, 2], first 2 is removed.
    [1, 2, 4, 2] - [2, 2]     # results in [1, 4].
    [1, 2, 4, 2] - [2, 2, 2]  # results in [1, 4], no match for the 3rd '2'.

The element test operator `in` tests whether the value lhs exists in list rhs. This operation is expensive to compute, if you need this operation frequently, consider using a set instead. Some examples of the element test operation:

    1 in [1, 2, 3]          == true
    4 in [1, 2, 3]          == false  # there is no 4 in [1, 2, 3]
    [1] in [[2], [1]]       == true
    [2, 1] in [[1, 2]]      == false  # [2, 1] != [1, 2]
    <int>[] in <list int>[] == false  # empty list contains no values.

There are also standard library functions for lists, see List functions for details.

### Set expressions

Literal sets are written as follows.

The first line shows the syntax of an empty set. The `Type` block denotes the element type of the set, for example `<int>{}` is an empty set of integer values.

The second line shows how to write a non-empty literal set value. It is a comma-separated sequence of expressions surrounded by curly brackets. The type of all expressions must be the same, and this is also the element type of the set. The order of the values in the literal is not relevant, and duplicate values are silently discarded. For example:

    set real xr = {1.0, 2.5, -31.28, 1.0}

assigns the set `{-31.28, 1.0, 2.5}` (any permutation of the values is allowed). By convention, elements are written in increasing order in this document.

Two set values are equal when they have the same number of element values contained, and each value of one set is also in the other set. The order of the elements in a set is not relevant, any permutation is equivalent.

Like lists, sets have no unary operators. They do have binary operators though. The operators are as follows.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `+` rhs | set T | set T | set T | Set union
lhs `-` rhs | set T | set T | set T | Set difference
lhs `*` rhs | set T | set T | set T | Set intersection
lhs `==` rhs | set T | set T | bool | Test for equality
lhs `!=` rhs | set T | set T | bool | Test for inequality
lhs `in` rhs | T | set T | bool | Element test
lhs `sub` rhs | set T | set T | bool | Sub-set test

The union of two sets means that the lhs elements and the rhs elements are merged into one set (and duplicates are silently discarded). Set difference makes a copy of the lhs set, and removes all elements that are also in the rhs operand. The result of the operation has the same type as the lhs set. Set intersection works the other way around, its result is a set with elements that exist both in lhs and in rhs. Some examples:

    set int xr = {1, 3, 7};
    set int yr;

    yr = xr + {1, 2};  # assigns {1, 2, 3, 7}
    yr = xs - {1, 2};  # assigns {3, 7}
    yr = xs * {1, 2};  # assigns {1}

The element test of sets tests whether the value lhs is an element in the set rhs. This operation is very fast. The sub-set test does the same for every element value in the lhs operand. It returns `true` is every value of the left set is also in the right set. A few examples:

    1 in {1, 3, 7}  == true
    9 in {1, 3, 7}  == false

    {1} sub {1, 3, 7}       == true
    {9} sub {1, 3, 7}       == false
    {1, 9} sub {1, 3, 7}    == false # All elements must be present.
    {1, 3, 7} sub {1, 3, 7} == true # All sets are a sub-set of themselves.

There are also standard library functions for sets, see Set functions for details.

### Dictionary expressions

Literal dictionaries are written using the syntax shown below.

An empty dictionary needs the key and value type prefix, for example `<string:int>{}` is an empty dictionary with strings as key, and integer numbers as value. Literal values of such a dictionary are:

    dict(string, int) d;  # Initialized with the empty dictionary.

    d = {"one": 1, "twenty-three": 23};

The key-value pairs can be put in any order. Also, the key value must be unique. Two dictionaries are equal when they have the same number of keys, each key in one dictionary is also in the other dictionary, and the value associated with each key also match pair-wise.

The binary operators of dictionaries are as follows.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `[` rhs `]` | dict(K:V) | K | V | Element access
lhs `+` rhs | dict(K:V) | dict(K:V) | dict(K:V) | Update
lhs `-` rhs | dict(K:V) | dict(K:V) | dict(K:V) | Subtraction
lhs `-` rhs | dict(K:V) | list K | dict(K:V) | Subtraction
lhs `-` rhs | dict(K:V) | set K | dict(K:V) | Subtraction
lhs `==` rhs | dict(K:V) | dict(K:V) | bool | Test for equality
lhs `!=` rhs | dict(K:V) | dict(K:V) | bool | Test for inequality
lhs `in` rhs | K | dict(K:V) | bool | Element test
lhs `sub` rhs | dict(K:V) | dict(K:V) | bool | Sub-set test

The element access operator accesses the value of a key. Querying the value of a non-existing key value is not allowed, however when used at the left side of an assignment, it acts as an adding operation. A few examples:

    dict(int:bool) d = {1:true, 2:false};
    bool b;

    b = d[1];     # assigns 'true' (the value of key 1).
    d[1] = false; # updates the value of key '1' to 'false'.
    d[8] = true;  # adds pair 8:true to the dictionary.

The `+` operation on dictionaries is an update operation. It copies the lhs dictionary, and assigns each key-value pair of the rhs dictionary to the copy, overwriting values copied from the lhs. For example:

    dict(int:bool) d = {1:true, 2:false};

    d + {1:false}   # result is {1:false, 2:false}
    d + {3:false}   # result is {1:true, 2:false, 3:false}

The subtraction operator only takes keys into consideration, that is, it makes a copy of the lhs dictionary, and removes key-value pairs where the key is also in the rhs argument (for subtraction of lists and sets, the elements are used, instead of the keys):

    dict(int:bool) d = {1:true, 2:false};

    d - {1:false}   # results in {2:false}, value of '1' is not relevant
    d - [1]         # results in {2:false}
    d - {1}         # results in {2:false}

As with list subtraction and set difference, the type of the result is the same as the type of the lhs dictionary.

The element test tests for presence of a key value, and the sub-set operation tests whether all keys of the lhs value are also in the rhs value. Examples:

    dict(int:bool) d = {1:true, 2:false};
    bool b;

    b = 2 in d;  # assigns 'true', 2 is a key in d.
    b = 5 in d;  # assigns 'false', 5 is not a key in d.

    {1:false} sub d # results in 'true', all keys are in d.

There are also standard library functions for dictionaries, see Dictionary functions for details.

### Tuple expression

A tuple expression is a value of a tuple type (explained in Tuple type). A tuple expression literal value is written as shown below.

A literal tuple is a comma separated sequence of expressions of length two or longer, surrounded by a pair of parentheses. The number of expressions and the type of each expression decide the tuple type. For example:

    type tup = tuple(bool b; real r);

    tup t = (true, 3.48);

The type named `tup` is a tuple type with a boolean field and a real field. The expression `(true, 3.48)` constructs the same tuple type, thus it can be assigned to variable `t`. Names of the fields are not relevant in this matching, for example variable declaration (and initialization) `tuple(bool z; real w) u = t` is allowed, since the types of the fields match in a pair-wise manner.

A field of a tuple can be accessed both for read and for assignment by the name of the field:

    bool c;

    c = t.b;     # Read the 'b' field.
    t.b = false; # Assign a new value to the 'b' field.

In the latter case, only the assigned field changes, all other fields keep the same value.

Tuples can also be packed and unpacked. Packing is assignment to all fields, while unpacking is reading of all fields into separate variables:

    real q;

    t = false, 3.8; # Packing of values into a tuple.

    c, q = t;       # Unpacking into separate variables.

Packing is very closely related to literal tuples above. The difference is that packing can be done only like above in an assignment to a tuple value, while a literal tuple works everywhere.

Unpacking is very useful when the right side (`t` in the example) is more complex, for example, the return value of a function call, as in `c, q = f();`. In such cases you don’t need to construct an intermediate tuple variable.

Packing and unpacking is also used in multi-assignment statements:

    a, b = 3, 4;   # Assign 3 to 'a', and 4 to 'b'.

    a, b = b, a;   # Swap values of 'a' and 'b'.

The latter works due to the intermediate tuple that is created as part in the assignment.

### File handle expressions

Variables of type `file` are created using a variable declaration with a `file` type, see File type for details about the type.

You cannot write a literal value for a file type (nor can you read or write values of this type), file values are created by means of the `open` function in the standard library, see File functions.

You can test whether two files are the same with the binary `==` and `!=` operators.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `==` rhs | file | file | bool | Test for equality
lhs `!=` rhs | file | file | bool | Test for inequality

Values of type `file` are used for writing output to a file using the Write statement, or for reading values from a file using the `read` function explained in Read expression. After use, a file should be closed with a `close` statement explained at Close statement.

### Read expression

The read expression reads a value of a given type from the keyboard or from a file. It has two forms:

`T` read(`T`)

  Read a value of type `T` from the keyboard.

`T` read(`file f, T`)

  Read a value of type `T` from the file opened for reading by file `f` (see the `open` function in File functions for details about opening files).

You can read values from types that contain data used for calculation, that is values of types `bool`, `int`, `real`, `string`, `list T`, `set T`, and `dict(K:V)`. Types `T`, `K`, and `V` must also be readable types of data (that is, get chosen from the above list of types).

Reading a value takes a text (with the same syntax as Chi literal values of the same type), and converts it into a value that can be manipulated in the Chi model. Values read from the text have to be constant, for example the input `time` cannot be interpreted as real number with the same value as the current simulation time.

### Timer expressions

Timers are clocks that count down to 0. They are used to track the amount of time you still have to wait. Timers can be stored in data of type `timer` (see Timer type for details of the type).

The standard library function `ready` exists to test whether a timer has expired. See Timer functions for details.

### Channel expressions

Channels are used to connect processes with each other. See the Channel type for details.

Usually, channels are created by variable declarations, as in:

    chan void s;
    chan int c, d;

This creates three channels, one synchronization channel `s`, and two channels (`c`, and `d`) communicating integers.

There is also a `channel` function to make new channels:

`chan T` channel(`T`)

  Construct a new channel communicating data type `T`. When `T` is `void`, a synchronization channel is created instead.

The only binary expressions on channels are equality comparison operations.

Expression | Type lhs | Type rhs | Type result | Explanation
--- | --- | --- | --- | ---
lhs `==` rhs | chan T | chan T | bool | Test for equality
lhs `!=` rhs | chan T | chan T | bool | Test for inequality

where `T` can be either a normal type, or `void`. There has to be an overlap between the channel directions (that is, you cannot compare a receive-only channel with a send-only channel).

### Distribution expressions

A distribution represents a stochastic distribution for drawing random numbers. It use a pseudo-random number generator. See Modeling stochastic behavior for a discussion how random numbers are used.

Variables of type distribution (see Distribution type) are initialized by using a distribution function from the standard library, see Distributions for an overview.

There is only one operator for variables with a distribution type, as shown below.

Expression | Type op | Type result | Explanation
--- | --- | --- | ---
`sample` op | dist bool | bool | Sample op distribution
`sample` op | dist int | int | Sample op distribution
`sample` op | dist real | real | Sample op distribution

The `sample` operator draws a random number from a distribution. For example rolling a dice:

    model Dice():
        dist int d = uniform(1, 7);

        # Roll the dice 5 times
        for i in range(5):
            writeln("Rolled %d", sample d);
        end
    end

### Process expressions

A process expression refers to a process definition. It can be used to parameterize the process that is being instantiated, by passing such a value to a `run` or `start` statement. (See Run and start statements for details on how to create a new process.) An example:

    proc A(int x):
        writeln("A(%d)", x);
    end

    proc B(int x):
        writeln("B(%d)", x);
    end

    proc P(proc (int) ab):
        run ab(3);
    end

    model M():
        run P(A); # Pass 'proc A' into P.
    end

Formal parameter `ab` of process `P` is a process variable that refers to a process taking an integer parameter. The given process definition is instantiated. Since in the model definition, `A` is given to process `P`, the output of the above model is `A(3)`.

### Instance expressions

Process instances represent running processes in the model. Their use is to store a reference to such a running process, to allow testing for finishing.

An instance variable is assigned during a `start` statement. (See Run and start statements for details on how to start a new process.)

The instance variable is used to test for termination of the instantiated process, or to wait for it:

    proc Wait():
        delay 4.52;
    end

    model M():
        inst w;

        start w = Wait();

        delay 1.2;
        writeln("is Wait finished? %b", finished(w));

        # Wait until the process has finished.
        finish w;
    end

`Wait` is a process that waits a while before terminating. In the `start` statement, instance variable `w` is set up to refer to instantiated process `Wait`. After assignment, you can use the variable for testing whether the process has terminated. In the example, the test result is written to the screen, but this could also be used as a guard in a select statement (See Select statement for details).

The other thing that you can do is to wait for termination of the process by means of the `finish` statement, see also Finish statement.

### Matrix expression

The syntax of a matrix literal value is as follows.

The literal starts with a `[` symbol, and ends with a `]` symbol. In between it has at least two comma-separated lists of real number values, separated with a `;` symbol.

Each comma-separated list of real number values is a row of the matrix. The number of columns of each row is the same at each row, which means the number of real number values must be the same with each list. As an example:

    matrix(2, 3) m = [1.0, 2.0, 3.0;
                      4.0, 5.0, 6.0]

`m` is a matrix with two rows and three columns. A comma separates two columns from each other, a semicolon separates two rows.

The syntax demands at least one semicolon in a literal matrix value, which means you cannot write a matrix literal with a single row directly. Instead, write a cast expression that converts a list of real numbers to a matrix with a single row. See Cast expressions for an explanation of cast expressions.

### Cast expressions

A cast expression converts a value from one type to another. The syntax of a cast expression is as follows.

You write the result type, followed by an expression between parentheses. The value of the expression is converted to the given type. For example:

    real v = 3.81;
    timer t;

    t = timer(v);  # Convert from real to timer (third entry in the table)

The conversion from a list to a matrix (the first entry in the table) is a special case in the sense that you also need to specify the size of the resulting matrix, as in:

    list real xs = [1, 2, 3];

    writeln("matrix with one row and three columns: %s", matrix(1, 3, xs));

The expected number of rows and columns given in the first two arguments must be constant. When the conversion is performed, the length of the given list must be the same as the number of columns stated in the second argument.

The number of available conversions is quite limited, below is a table that lists them.

Value type | Result type | Remarks
--- | --- | ---
list | matrix | Conversion of a list to a matrix with one row
list | set | Construct a set from a list
real | timer | Setting up a timer
timer | real | Reading the current value of a timer
string | bool | Parsing a boolean value from a string
string | int | Parsing an integer number from a string
string | real | Parsing a real number from a string
bool | string | Converting a boolean to a string representation
int | string | Converting an integer to a string representation
real | string | Converting a real number to a string representation
int | real | Widening an integer number to a real number

The first entry exists for creating matrices with one row (which you cannot write syntactically). The second entry constructs a set from a list of values. The element type of the list and the resulting set are the same.

The pair of conversions between timer type and real number type is for setting and reading timers, see Timers for their use.

The conversions from string to boolean or numeric allows parsing of a string. The other way around is also possible, although this is usually done as part of a write statement (see Write statement for details).

The final entry is for widening an integer to a real number. The other way around (from a real number to an integer number) does not exist as cast, but there are stdlib functions ceil, floor, and round available instead (explained in Real number functions).

### Function call expressions

A function call starts a function to compute its result value from the input parameters. The syntax is as follows.

The `Expression` before the open parenthesis represents the function to call. Often this is a simple name like `size` (the name of one of the standard library functions), but you can have more complicated expressions.

The sequence of expressions inside the parentheses denote the values of the input parameters of the functions. Their type has to match with the type stated in the formal parameter at the corresponding position.

The result of the function call is a value with the same type as stated in the return type of the function definition.

### Operator priorities

Operator priorities aim to reduce the number of parentheses needed in expressions. They do this by make choices in the order of applying operators on their arguments. For example, `1 + 2 * 3` can be interpreted as `(1 + 2) * 3` (if the addition operation is applied first), or as `1 + (2 * 3)` (if the multiplication operation is performed first).

In the following table, the order of applying operators in the Chi language is defined.

Priority | Operators
--- | ---
1 | (unary) `sample`
2 | unary `+`, unary `-`
3 | `^`
4 | `*`, `/`, `div`, `mod`
5 | `+`, `-`
6 | `<`, `<=`, `==`, `!=`, `>=`, `>`, `in`, `sub`
7 | (unary) `not`
8 | `and`
9 | `or`

Operators with a smaller priority number get applied before operators with a higher priority number. Operators with the same priority get applied from left to right.