Function body elements

A body of a function consists of sequence of elements. Here are listed most important of these elements.

Variables declaration

See Variables.

Auto variable declaration

See auto variables.

Simple expression

Usually this is needed in order to call some function with side-effects.

Foo(); // Call a function, that may have side-effects
Add( 5, 7 ); // Call a function with or without side-effects

Assignment

Assignment consists of left part - for destination and right part - for source.

x = 2; // Assign a numeric value to a variable
x = Foo() + Bar() - 66; // Assign a complex expression result to a variable
Min( x, y )= 0; // It's possible too, if the result of "Min" function is a mutable reference

Operation combined with assignment

There are following operations combined with assignment:

  • += - addition
  • -= - subtraction
  • *= - multiplication
  • /= - division
  • %= - remainder
  • &= - bitwise AND
  • |= - bitwise OR
  • ^= - bitwise XOR
  • =<< - left shift
  • =>> - right shift

An operation with assignment is equivalent to a call to corresponding binary operator for left and right parts of the operation with following assignment of the result to the left part.

x += 2; // Increase value of "x" by 2
x /= Foo() + Bar() - 66; // Divide variable "x" by the result of the right expression and than save result into "x"
Min( x, y ) &= 0xFF; // Set upper bits of the "Min" call result variable to zero

Increment and Decrement

++ increases the result of an integer expressions by one, -- decreases it.

++ x;
-- x;
++ Min( x, y );

Control flow elements

See Control flow.

static_assert

See static_assert.

halt

See Halt.

Block

A block consists of sequence of elements in {}. It may include elements listed above and other blocks.

A block is used primary for new variables scope creation. A variable defined in a block is visible inside this block and nested blocks. Variables defined in a block have a lifetime limited to the end of this block. When control flow reaches the end of the block lifetimes of all variables defined in this block end.

It’s possible to define inside a block a variable with the same name as in one of outer blocks. After that outer variable will no longer be accessible.

fn Foo()
{
    var i32 mut x= 0;
    {
         ++x; // Modify value of outer variable
         var f64 mut x= 3.14; // Define a variable with the same name as a variable in outer block. Now the outer "x" variable will not be accessible until the end of the current block.
         x= 0.0; // Modify a variable of this block.
         var i32 mut y= 0;
    }
    --y; // Error - name "y" not found
}

A block may have a label. This label may be used in break operators inside this block. In such case break works for this block only if a label is specified in it. break without a label relates to a current loop, but not to a block marked with a label. continue for a label of a block is not possible, the compiler will produce an error in such case.

fn Foo(bool cond)
{
   {
       if( cond )
       {
           break label block_end;
       }
       // some other code
   } label block_end
}

There are also unsafe blocks. See Unsafe code.

with operator

This operator allows to perform some action with a result of an expression and if necessary extend the lifetime of temporary variables inside this expression. This operator contains optional reference and mutability modifiers and a name for the expression result.

with is helpful to use as an alternative to a block, inside that a variable is defined and some operations with it are performed, in cases where the lifetime of the variable should be limited. Also it is helpful to use with in template code where it is not clear whether a result of an expression is a variable or a reference, because with (unlike var and auto) allows to create a reference to a temporary variable.

Usage examples:

with( x : Foo() )
{
    Bar(x);
    return x + 1;
}
with( &mut x : s.Get() )
{
    ++x;
}