Skip to content

Core expressions (ref)

Alex Zimin edited this page Jul 11, 2011 · 4 revisions

<< Back to Reference Manual.

Table of Contents

Core expressions

core_expr =
  function_call
| assignment
| match_expr
| throw_expr
| try_catch_expr
| try_finally_expr
| unary_operator_application
| binary_operator_application
| type_cast
| type_enforcement
| one_case_matching
| dynamic_type_check
| checked_unchecked_block
| block
| array_constructor
| value_definition
| local_function_definition
| mutable_value_definition

Function call

function_call =
Primary_expressions_(ref):primary_expr '(' [ parameter { ',' parameter } ] ')'

parameter =
[ 'ref' ] [ IDENTIFIER '=' ] expr
| [ 'out' ] [ IDENTIFIER '=' ] expr 

Call a function with given parameters. The type of the function call expression is the same as the type of the function return value; that is, if the function's type is 'a -> 'b, then the type of the function call expression is 'b. The value of the whole expression is the return value of the function.

ref and out are used to denote a parameter passed by reference.

Assignment

assignment =
primary_expr '=' expr

Assign a value to a variable. The left side of the assignment expression must evaluate to a mutable variable. The type of the assignment is always void.

In earlier versions there was <- assignment operator, which is now (Nemerle 0.2.x) deprecated.

Match expression

match_expr = 'match' '(' expr ')' '{' [ '|' ] match_case { '|' match_case } '}'

match_case = guarded_pattern { '|' guarded_pattern } '=>' action

action = sequence

guarded_pattern = pattern [ 'when' expr ] 

See: pattern

expr is matched sequentially to the patterns in given match cases. If one of the patterns is consistent with the value of expr, then the corresponding computation branch of the match case is evaluated. Patterns in all the match cases must be of the same type. Expressions being computation branches in all the match cases must share a common super type, which is the type of the entire match.

A guarded pattern requires expression expr to be of type bool. An expression e satisfies the guarded pattern only if it is pattern-matched with pattern and expression expr is evaluated to true.

An expression e satisfies this match case if and only if it satisfies one of the guarded patterns in this match case.

Throw expression

throw_expr =
'throw' expr

Throws given exception. The type of the expression thrown must be subtype of System.Exception.

Try..catch expression

try_catch_expr =
'try' block 'catch' 
'{' [ '|' ] try_catch_handler { '|' try_catch_handler } '}' [ 'finally' block ]

try_catch_handler =
identifier_or_dummy [ 'is' type ] [ 'when' expr ] '=>' expr 

If the evaluation of expr does not throw any exception, then the result is that of the evaluation of expr. Otherwise, the runtime type of the exception which was thrown is compared against each type description in handlers. The first matching handler is executed and its value returned. If none of the handlers matches, the exception is propagated. The type of the whole expression is the same as type of guarded expression. The value is the value of expression or launched handler. Please consult .NET specification if you want to know more about exceptions.

The optional finally clause has the same meaning as below.

Try..finally expression

'try' block 'finally' block

Evaluates the first expression and -- regardless of whether the evaluation has finished correctly or some exception has been thrown during the evaluation -- the second expression is evaluated. The value (and thus the type) of the whole expression is the value of the first expression.

Unary operator application

unary_operator_applications =
OPERATOR expr

Unary operator for numeric types:

  • ++ prefix increment with void return type
  • -- prefix decrement with void return type
  • + a noop
  • - negation
Integer types also have the ~ (bitwise negation) defined. Boolean type has ! (boolean negation).

User defined types can have some other operators defined.

Binary operator application

expr OPERATOR expr```

There is a number of standard operators, which are predefined for
arithmetic types (floating point and integer):

* <code>-</code>  subtraction
* <code>*</code>  multiplication
* <code>/</code>  division
* <code>&lt;</code>  less comparison
* <code>&gt;</code>  more comparison
* <code>&lt;=</code>  less-equals
* <code>>=</code>  more-equals
* <code>==</code>  equality
* <code>!=</code>  inequality
* <code>+=</code>  addition with assignment
* <code>-=</code>  subtraction with assignment
* <code>*=</code>  multiplication with assignment
* <code>/=</code>  division with assignment

For integer types only (int, uint, short, ushort, long, ulong, byte,
sbyte) there are:

* <code><<</code>  left bitwise shift
* <code>>></code>  right bitwise shift
* <code>%</code>  modulus
* <code>%=</code>  modulus with assignment
* <code><<=</code>  left bitwise shift with assignment
* <code>>>=</code>  right bitwise shift with assignment
* <code>|</code>  bitwise or
* <code>&</code>  bitwise and
* <code>^</code>  bitwise xor
* <code>%||</code>  bitwise `or' returning true iff result of `or' is nonzero
* <code>%&&</code>  bitwise `and' returning true iff result of `and' is nonzero
* <code>%^^</code>  bitwise `xor' returning true iff result of `xor' is nonzero
* <code>|=</code>  bitwise or with assignment
* <code>&=</code>  bitwise and with assignment
* <code>^=</code>  bitwise xor with assignment

==  Type cast ==
```bnf
type_cast =
expr ':>' type

This expression allows dynamic type coercion. It is done during runtime and if it cannot be realized then System.InvalidCastException is thrown. If it succeeds, the type of this expression is equal to the type of type.

Type enforcement

expr ':' type```

This expression allows static type enforcement. It is checked during
compile-time and an error is reported if expr type is not a subtype of
type. It allows only type widening. If it succeeds, the type of this
expression is equal to the type of type.

== One-case matching ==
```bnf
one_case_matching =
expr 'is' pattern

Equivalent to match (expr) { pattern => true | _ => false }. The usage of matches instead of is is now deprecated.

11.13. Dynamic type check

dynamic_type_check =
expr 'is' type

Equivalent to match (expr) { _ is type => true | _ => false }.

checked/unchecked blocks

checked_unchecked_block =
'checked' expr
| 'unchecked' expr

Turn on/off overflow checking for arithmetic operators. Checks are on by default.

Block expression

sequence =
expr { ';' expr } [ ';' ] 

Expressions in the sequence are evaluated sequentially, and the value (and thus the type) of the sequence is the value of the last expression in the sequence.

Values of expression (except for the last one) are ignored, and thus if the type of some expression is not void -- a warning is generated.

The ; is optional after after } inside a sequence.

block = 
'{' sequence '}'
|  '{'  '|' match_case  {  '|'  match_case  }  '}'

The first form is just a standard execution of a sequence of expressions. The value (and type) of this block is the same as the last expression in the sequence. Note that block is always implicitly followed by ;, so to use it's value not in the end of some expression you'll need to surround it with ( ).

The second form is a shortcut for matching parameters of a defined function with a given list of patterns. It is equivalent to making a tuple from parameters of function and creating match expression.

def f (p1, p2, p3) 
{ 
  | (1, 3, "a") => 1
  | _ => 2
}

translates to

def f (p1, p2, p3) 
{ 
  match ((p1, p2, p3)) {
    | (1, 3, "a") => 1
    | _ => 2
  }
}

It is also to note that when a function has only one parameter, the matching goes just on this parameter itself (no one-element tuple is created).

Named block

IDENTIFIER ':' block

Named block is a replacement for imperative construction like 'return' and 'breack'.

You can exit from a named block by calling it as function. And at the same time you can return value.

Example:

def list1 = [4, 3, 5];
def list2 = [1, 2, 3];

def foundValue = 
  returnValue :
  {
    foreach (x in list1)
      foreach (y in list2)
        when (x == y)
          returnValue(x); // exit from two loops

    -1 // return by defaulte (if returnValue has not been called)
  };
  
WriteLine(foundValue); // print: 3

Array constructor

'array' [ '.' '[' NUMBER_LITERAL ']' ] '[' [ { expr ',' } expr ] ']'

Create an array consisting of given elements. All elements must be of the same type. If the elements are of the type 'a then the whole expression is of the type array ['a].

The number in [] is array rank. It defaults to 1. If rank is specified, rows, columns and so on are specified using nested [], like in:

array .[2] [[1, 2], [3, 4], [5, 6]]
array .[3] [[[1, 2], [10, 20]], [[11, 12], [110, 120]]]

Value definition

value_definition =
'def' pattern '=' expr

Defines the binding between the variables in the pattern and the value of the expression expr which will be known to all subsequent expressions in the current block.

Local function definition

local_function_definition =
'def' method_header block [ { 'and' method_header block } ]

Defines the functions which will be known to all subsequent expressions in the current block. Names of all defined functions are put into the symbol space before their bodies are parsed. (Note that it implies that body of defined function is a subsequent expression too)

Mutable value definition

'mutable' IDENTIFIER '=' expr

Defines a new variable, value of which can be changed at any time using the assignment expression.

Clone this wiki locally