Vala Reference Manual [Draft]

Expressions

Expressions are short pieces of code that define an action that should be taken when they are reached during a program's execution. Such an operation can be arithmetical, calling a method, instantiating a type, and so on. All expressions evaluate to a single value of a particular type - this value can then be used in another expression, either by combing the expressions together, or by assigning the value to an identifier.

When expressions are combined together (e.g. add two numbers, then multiply the result by another: 5 + 4 * 3), then the order in which the sub-expressions are evaluated becomes significant. Parentheses are used to mark out which expressions should be nested within others, e.g. (5 + 4) * 3 implies the addition expression is nested inside the multiplication expression, and so must be evaluated first.

When identifiers are used in expressions they evaluate to their value, except when used in assignment. Assignment's are a special case of expressions where an identifier is not considered an expression in itself and is therefore not evaluated. Some operations combine assignment with another operation (e.g. increment operations,) in which cases an identifier can be thought of as an expression initially, and then just an identifier for assignment after the overall expression has been evaluated.

expression: literal identifier nested-expression arithmetic-expression bitwise-expression relational-expression logical-expression assigment-expression flag-expression class-instantiation-expression struct instantiation-expression member-access-expression element-access-expression invocation-expression cast-expression conditional-expression ownership-transfer-expression pointer-indirection-expression nested-expression: ( expression ) arithmetic-expression: addition-expression subtraction-expression negation-expression multiplication-expression division-expression modulo-expression bitwise-expression: left-shift-expression right-shift-expression bitwise-and-expression bitwise-or-expression bitwise-xor-expression bitwise-not-expression boolean-expression: relational-expression logical-expression is-expression relational-expression: less-than-expression less-than-or-equal-expression more-than-expression more-than-or-equal-expression equality-expression inequality-expression logical-expression: logical-and-operation logical-or-operation logical-not-operation assigment-expression: assignment-expression assignment-to-signal-expression assignment-with-addition-expression assignment-with-subtraction-expression prefix-increment-expression postfix-increment-expression prefix-decrement-expression postfix-decrement-expression assignment-with-multiplication-expression assignment-with-division-expression assignment-with-modulo-expression assignment-with-left-shift-expression assignment-with-right-shift-expression assignment-with-bitwise-and-expression assignment-with-bitwise-or-expression assignment-with-bitwise-xor-expression flag-expression: flag-combination-expression flag-separation-expression cast-expression: explicit-case-expression as-expression is-expression

Literal expressions

Each literal expression instantiates its respective type with the value given.

Integer types... -?[:digit:]+

Floating point types... -?[:digit:]+(.[:digit:]+)?

Strings... "[^"\n]*". """.*"""

Booleans... true|false

A final literal expression is null. This expression evaluates to a non-typed data instance, which is a legal value for any nullable type (see Types/Nullable types.)

Arithmetic operations

Binary operators, taking one argument on each side. Each argument is an expression returning an appropriate type.

Applicable, unless said otherwise, where both operands evaluate to numeric types, where:

numeric-type: integer-type floating-point-type

Where at least one operand is a of floating point type, the result will be the sam type as the largest floating point type involved. Where both operands are of integer types, the result will have the same type as the largest of the integer types involved.

Addition/Subtraction:

addition-expression: expression + expression subtraction-expression: expression - expression negation-expression: - expression

Adds/Subtracts the second argument to/from the first. Negations is equivalent to subtraction the operand from 0.

Overflow?

Multiplication/Division:

multiplication-expression: expression * expression division-expression: expression / expression

Multiplies/divides the first argument by the second.

If both operands are of integer types, then the result will be the quotient only of the calculation (equivalent to the precise answer rounded down to an integer value.) If either operand is of a floating point type, then the result will be as precise as possible within the boundaries of the result type (which is worked out from the basic arithmetic type rules.)

Modulo Arithmetic:

Only applicable to integer types.

modulo-expression: expression % expression

Remainder...

Bitwise operations

All only applicable to integer types.

left-shift-expression: expression << expression right-shift-expression: expression >> expression

Shifts the bits of the left argument left/right by the number represented by the second argument. Second argument must be an integer type?

allowed lhs types?

Undefined for shifting further than data size, e.g. with a 32 bit integer...

bitwise-and-expression: expression & expression

Documentation

bitwise-or-expression: expression | expression

Documentation

bitwise-xor-expression: expression ^ expression

Documentation

bitwise-not-expression: ~ expression

Documentation

Relational operations

Result in a value of bool type.

Applicable for comparing two instances of any numeric type, or two instances of string type. Where numeric with at least one floating point type instance, operands are both converted to the largest floating point type involved. Where both operands are of integer type, both are converted to the largest integer type involved. When both are strings, they are lexically compared somehow.

less-than-expression: expression < expression less-than-or-equal-expression: expression > expression more-than-expression: expression <= expression more-than-or-equal-expression: expression >= expression

Documentation

equality-expression: expression == expression

Documentation

inequality-expression: expression != expression

Documentation

Logical operations

Applicable to boolean type operands, return value is of boolean type. No non boolean type instances are automatically converted.

logical-and-expression: expression && expression

Documentation

logical-or-expression: expression || expression

Documentation

logical-not-expression: ! expression

Documentation

Assignment operations

Value assigned to identifier on left. Type must match.

When assignment includes another operation natural result type must match the declared type of variable which is the left hand side of the expression. e.g. Let a be an int instance with the value 1, a += 0.5 is not allowed, as the natural result type of 1 + 0.5 is a float, not an int.

assignment-expression: identifier = expression

Documentation

Addition/Subtraction with assignment:

assignment-with-addition-expression: identifier += expression assignment-with-subtraction-expression: identifier -= expression

Same operation as previous, lhs must be identifier to which result will be reassigned after operation is completed.

Increment/Decrement:

prefix-increment-expression: ++ identifier postfix-increment-expression: identifier ++ prefix-decrement-expression: -- identifier postfix-decrement-expression: identifier --

One argument, must be an identifier referencing a ...? Value is increased/decreased by 1, and then result is reassigned to the variable. Result type is the same as that of the argument. Result value is initial arg value for postfix operator, final arg value for prefix operator.

Multiplication/Division with assignment:

assignment-with-multiplication-expression: identifier *= expression assignment-with-division-expression: identifier /= expression

Same operation as previous, lhs must be identifier to which result will be reassigned after operation is completed.

Modulo with assignment:

assignment-with-modulo-expression: identifier %= expression

Same operation as previous, lhs must be identifier to which result will be reassigned after operation is completed.

Bit Shifting with assignment:

assignment-with-left-shift-expression: identifier <<= expression assignment-with-right-shift-expression: identifier >>= expression

Same operation as previous, lhs must be identifier to which result will be reassigned after operation is completed.

assignment-with-bitwise-and-expression: identifier &= expression

Documentation

assignment-with-bitwise-or-expression: identifier |= expression

Documentation

assignment-with-bitwise-xor-expression: identifier ^= expression

Documentation

Flag operations

Flag types are a variation on enumerated types, in which any number of flag values can be combined in a single instance of the flag type. There are therefore operations available to combine several values in an instance, and to find out which values are represented in an instance.

flag-combination-expression: expression | expression

Where both expressions evaluate to instances of the same flag type, the result of this expression is a new instance of the flag type in which all values represented by either operand are represented.

flag-recombination-expression: expression ^ expression

Where both expressions evaluate to instances of the same flag type, the result of this expression is a new instance of the flag type in which all values represented by exactly one of the operands are represented.

flag-separation-expression: expression & expression

Where both expressions evaluate to instances of the same flag type, the result of this expression is a new instance of the flag type in which all values represented by both operands are represented.

Type operations

is-expression: expression is type-name

Performs a runtime type check on the instance resulting from evaluating the the nested expression. If the instance is an instance of the type described (with, for example, a class or interface name,) the overall expression evaluates to true.

Casting:

cast-expression: ( type-name ) expression

A cast expression returns the instance created in the nested expression as an instance of the type described. If the nested expression evaluates to an instance of a type that is not also an instance of the given type, the expression is not valid. If you are not sure whether the cast is valid, instead use an "as" expression.

as-expression: expression as type-name

An "as" expression combines an "is" expression and a cast operation, with the latter depending on the former. If the nested expression evaluates to an instance of the given type, then a cast is performed and the expression evaluates to the result of the nested expression cast as the given type. Otherwise, the result is null.

Conditional expressions

Allow a conditional in a single expression, provided all subparts are also expressions, i.e. no statements.

conditional-expression: boolean-expression ? conditional-true-clause : conditional-false-clause conditional-true-clause: expression conditional-false-clause expression

First the boolean-expression is evaluated. If true, then the conditional-true-clause is evaluated, and its result is the result of the conditional expression. If the boolean expression evaluates to false, then the conditional-false-clause is evaluated, and its result becomes the result of the conditional expression.

Invocation expressions

invocation-expression: identifier ( [ call-params-list ] ) call-params-list: call-param [ , call-params-list] call-param: identifier

Delegates... See Delegates

Firing a signal is basically the same. See Classes/Signals

Class instantiation

To instantiate a class (create an instance of it) use the new operator. This operator takes a the name of the class, and a list of zero or more properties to set on the object - the construction properties.

class-instantiation-expression: new type-name ( param-list )

Struct instantiation

struct instantiation-expression: type-name ( param-list ) [ { initial-values } ] initial-values: initial-value [ , initial-values ] initial-value: field-name = expression

Member access expressions

To access members of another scope.

member-access-expression: identifier [ . member-access-expression ]

The identifier can be either the name of a namespaces, class, etc, or the identifier of a variable, whose data instance can contain members, e.g. an instance of a classed-type.

Array instantiation

To ...

array-instantiation-expression: new type-name [ expression ] dimension-separators: , dimension-separators ,

expression must be of an integer-type and more than 0?

Element access

[] - mention both get and set

element-access-expression: identifier [ expression ]

Ownership transfer expressions

ownership-transfer-expression: # identifier

When an instance of a reference type is assigned to a variable or field, it is possible to request that the ownership of the instance is passed to the new field or variable. The precise meaning of this depends on the reference type, for an explanation of ownership, see Concepts/References and ownership. The identifier in this expression must refer to an instance of a reference type.

Note that similar syntax is used to define that a method parameter should take ownership of a value assigned to it. For this, see Methods.

Pointer expressions

pointerto-expression: &identifier

Where the identifier is for an instance of a value type, this expression evaluates to a pointer to the instance.

pointer-indirection-expression: *identifier

Where the identifier is for an instance of a pointer type to a value type, this expression evaluates to an instance of the type to which the expression was a pointer.

pointer-member-access-expression: expression->identifier

When the sub-expression evaluates to an instance of a pointer type to a reference type, this expression evaluates to the member, of the reference type instance, described by the identifier.