13. Expressions
Expressions can only exist within a statement or another expression.
13.1. Table of Operator precedence
The following is a table containing all of the precedences and associativities of the operators in Gazprea.
Precedence 
Operators 
Associativity 

(Highest) 1 

left 
2 

left 
3 

N/A 
4 
unary 
right 
5 

right 
6 

left 
7 

left 
8 

left 
9 

left 
10 

left 
11 

left 
12 

left 
(Lowest) 13 

right 
13.2. Generators
A generator may be used to construct either a vector or a matrix. A generator creates a value of a vector type when one domain variable is used, a matrix type when two domain variables are used. Any other number of domain variables will yield an error.
A generator consists of either one or two domain expressions,
and an additional expression on the right hand side of the bar (
).
This additional expression is used to create the generated values. For example:
integer[10] v = [i in 1..10  i * i];
/* v[i] == i * i */
integer[2, 3] M = [i in 1..2, j in 1..3  i * j];
/* M[i, j] == i * j */
The expression to the right of the bar (
), is used to generate the
value at the given index.
Let T
be the type of the expression to the right of the bar (
). Then,
if the domain of the generator is a vector of size N
, the result will be a
vector of size N
with element type T
. Otherwise, if the domain of the
generator is a matrix of size N
x M
, the result will be a matrix of size
N
x M
with element type T
.
Generators may be nested, and
may be used within domain expressions. For instance, the generator below
is perfectly legal:
integer i = 7;
/* The domain expression should use the previously defined i */
integer[*] v = [i in [i in 1..i  i]  [i in 1..10  i * i][i]];
/* v should contain the first 7 squares. */
13.3. Filters
Filters are used to accumulate elements into vectors. Each filter contains a single domain expression, and a list of commaseparated predicates.
The result of a filter operation is a tuple. This tuple contains a field for each of the predicates in order. Each field is a vector containing only the elements from the domain which satisfied the predicate expressions. Each filter result has an additional field which is a vector containing all of the values in the domain which did not satisfy any of the predicates. For example:
/* x == ([3], [2], [2, 4], [1, 5]) */
var x = [i in 1..5 & i == 3, i == 2, i % 2 == 0];
/* y == ([1, 3, 5], [2, 4]) */
var y = [i in 1..5 & i % 2 == 1);
There must be at least one predicate expression
13.4. Domain Expressions
Domain expressions consist of an identifier denoting an iterator variable and
an expression that evaluates to any vector type.
Domain expressions can only appear within iterator loops, generators,
and filters. A domain expression is a way of declaring a variable that
is local to the loop, generator, or filter, that takes on values from
the domain expression vector in order.
Domain expressions must evaluate to a type, which means empty literal vectors
yield a TypeError
.
The scope of the domain variables (the left hand side of the declaration) is
within the body of the generator, filter, or loop.
The domain expressions (the right hand side) are all evaluated before any of the
domain variables are initialized, and therefore the domain expression scope is
the one enclosing the iterator loop, generator, or filter.
For instance:
integer i = 7;
/* This will print 1234567 */
loop i in 1..i {
i > std_output;
}
Domain variables are not initialized when they are declared. For instance, in loops they are initialized at the start of each execution of the loop’s body statement. However, we may chain domain variables using commas, like in iterator loops, or matrix generators.
integer i = 2;
/* The "i"s both domain expressions are at the same scope, which is
* the one enclosing the loop. Therefore the output is: 000012024
*/
loop i in 0..i, j in 0..i {
i * j > std_output;
}
The domain for the domain expression is only evaluated once. For instance:
integer x = 1;
/* 1..x is only evaluated the first time the loop executes, so it is
simply 1..1, and not an infinite loop. */
loop i in 1..x {
x = x + 1;
}
This is true for domain expressions within generators and filters as well.
Iterator variables can be assigned to and redeclared within the enclosed iterator loop. The variable is reinitialized according to the expression each iteration.
loop i in 1..6 {
integer i = 5;
}