-
Notifications
You must be signed in to change notification settings - Fork 89
Core expressions (ref)
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 =
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 =
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_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_expr =
'throw' expr
Throws given exception. The type of the expression thrown must be subtype of
System.Exception
.
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' 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_applications =
OPERATOR expr
Unary operator for numeric types:
-
++
prefix increment with void return type -
--
prefix decrement with void return type -
+
a noop -
-
negation
~
(bitwise negation) defined.
Boolean type has !
(boolean negation).
User defined types can have some other operators defined.
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><</code> less comparison
* <code>></code> more comparison
* <code><=</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.
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_block =
'checked' expr
| 'unchecked' expr
Turn on/off overflow checking for arithmetic operators. Checks are on by default.
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).
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' [ '.' '[' 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 =
'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 =
'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' IDENTIFIER '=' expr
Defines a new variable, value of which can be changed at any time using the assignment expression.