# Syntax

In Haxe, all statements are expressions, which means they can be nested. For example, `foo(if (x == 3) 5 else 8)` is valid Haxe. As this example shows, every expression returns a value of a given type.

# Constants

Here are some examples of constants in Haxe:

```    0; // Int
-134; // Int
0xFF00; // Int

123.0; // Float
.14179; // Float
13e50; // Float
-1e-99; // Float

"hello"; // String
"hello \"world\" !"; // String
'hello "world" !'; // String

true; // Bool
false; // Bool

null; // Unknown<0>

~/[a-z]+/i; // EReg : regular expression```

Notice that `null` has a special value, since any value can be `null`. Notice also that it is not `Dynamic`. This will be explained in detail when we introduce type inference.

# Operations

The following operations can be used, in order of priority:

• Unary operations (see next section below).
• `e1 % e2` : calculates e1 modulo e2, Return `Int` if they were both `Int`, otherwise return `Float`.
• `e1 / e2` : divide two numbers. Always return `Float`.
• `e1 * e2` : multiply two numbers. Same return type as modulo.
• `e1 - e2` : Subtract `Int`s or `Float`s. Same return type as modulo.
• `e1 + e2` : perform addition. Same return type as modulo.
• `<< >> >>>` : perform bitwise shifts between two `Int` expressions. Returns `Int`.
• `| & ^` : perform bitwise operations between two `Int` expressions. Returns `Int`.
• `== != > < >= <=` : perform normal or physical comparisons between two expressions sharing a common type. Returns `Bool`.
• `e1...e2` : Build an IntIter from `e1` to `e2` - see Iterators for more information.
• `e1 && e2` : If `e1` is `false` then `false` else evaluate `e2` . Both `e1` and `e2` must be `Bool`.
• `e1 || e2` : If `e1` is `true` then `true` else evaluate `e2` . Both `e1` and `e2` must be `Bool`.
• and `+= -= *= /= %= &= |= ^= <<= >>= >>>=` : assign after performing the corresponding operation
• `v = e` : assign a value to an expression, returns `e`

Note: Associativity of operators can be found here here

# Unary operations

The following unary operations are available :

• `!` : boolean not. Inverse the expression `Bool` value.
• `-` : negative number, change the sign of the `Int` or `Float` value.
• `++` and `--` can be used before or after a variable. When used before, they first increment the corresponding variable and then return the incremented value. When used after, they increment the variable but return the value it had before incrementation. Can only be used with `Int` or `Float` variables.
• `~` : ones-complement of an `Int`.

Note: `~` is usually used for 32-bit integers, so it is incompatible with Neko's 31-bits integers.

# Parentheses

Surrounding an expression with parenthesis will give that expression higher priority when it is to be evaluated. The type of `( e )` is the same as `e`, and they both evaluate to the same value.

# Blocks

Blocks are a group of several expressions. The syntax of a block is:

```    {
e1;
e2;
// ...
eX;
}```

A block evaluates to the type and value of the last expression of the block. For example :

`    { f(); x = 124; true; }`

This block is of type `Bool` and will evaluate to `true`.

The empty block `{ }` evaluates to `Void`.

# Variable Naming

Variable names are case sensitive in Haxe. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

# Local Variables

Local variables can be declared in blocks using `var`, as the following sample shows:

```    {
var x;
var y = 3;
var z : String;
var w : String = "";
var a, b : Bool, c : Int = 0;
}```

A variable can be declared with an optional type and an optional initial value. If no value is given then the variable is `null` by default. If no type is given, then the variable type is `Unknown` but will still be strictly typed. This will be explained in details when introducing type inference.

Several local variables can be declared in the same `var` expression.

Local variables are only defined until the block they're declared in is closed. They can not be accessed outside the block in which they are declared (i.e. Haxe has lexical scoping).

# Identifiers

When a variable identifier is resolved in the following order of precedence:

• local variables, last declared having priority
• class members (current class and inherited fields)
• current class static fields
• enum constructors that have been either declared in this file or imported
```    enum Axis {
x;
y;
z;
}

class C {
static var x : Int;
var x : Int;

function new() {
{
// x at this point means member variable this.x
var x : String;
// x at this point means the local variable
}
}

function f(x : String) {
// x at this point means the function parameter
}

static function f() {
// x at this point means the class static variable
}
}

class D {
function new() {
// x means the x Axis
}
}```

Type identifiers are resolved according to the imported packages, as we will explain later.

# Field access

Member access is done using the traditional dot notation :

`    o.field`

# Calls

You can call functions using parentheses and commas in order to delimit arguments. You can call methods by using dot access on objects :

```    f(1,2,3);
object.method(1,2,3);```

# New

The `new` keyword is used to create a class instance. It needs a class name and can take parameters :

```    a = new Array();
s = new String("hello");```

# Arrays

You can create arrays from a list of values like this:

`    var a : Array<Int> = [1,2,3,4];`

This is called an array literal.

Notice that Array takes one type parameter - the type of the items stored in the Array. All items in the array have to be of this type - this ensures type safety. (If you want a heterogeneous array, try `Array<Dynamic>` — we'll learn about that in a bit.)

Multidimensional arrays can be created by nesting these type parameters in the declaration:

```    var a : Array<Array<Int>> = [
[1, 2, 3],
[4, 5],
[6, 7, 8, 9], // Terminal comma is permitted but ignored.
];```

You can read and write into an Array by using the following traditional bracket access :

```    first = a[0];
a[1] = value;```

The array index must be of type `Int`.

Also see Array Comprehension for more advanced array features.

# If

Here are some examples of `if` expressions :

```    if (life == 0) destroy();
if (flag) 1 else 2;```

Here's the generic syntax of `if` expressions :

`    if( expr-cond ) expr-1 [else expr-2]`

First `expr-cond` is evaluated. It must be of type `Bool`. If it evaluates to `true` then `expr-1` is evaluated, otherwise, if there is an `expr-2` then it is evaluated instead.

If there is no `else`, and the `if` expression is false, then the entire expression has type `Void`. If there is an `else`, then `expr-1` and `expr-2` must be of the same type and this will be the type of the `if` expression :

```    var x : Void = if( flag ) destroy();
var y : Int = if( flag ) 1 else 2;```

In Haxe, `if` is similar to the ternary C `a?b:c` syntax. You can use ternary syntax if you want.

`    var x  = ( x < upperBound )? x: upperBound;`

As an exception, if an `if` block is not supposed to return any value (like in the middle of a Block) then both `expr-1` and `expr-2` can have different types and the `if` block type will be `Void`.

# While

While are standard loops that use a precondition or postcondition :

```    while( expr-cond ) expr-loop;
do expr-loop while( expr-cond );```

For example :

```    var i = 0;
while( i < 10 ) {
// ...
i++;
}```

Or using `do...while` :

```    var i = 0;
do {
// ...
i++;
} while( i < 10 );```

Like with `if`, the `expr-cond` in a while-loop type must be of type `Bool`.

Another useful example will produce a loop to count from 10 to 1:

```    var i = 10;
while( i > 0 ) {
.......
i--;
}```

# For

For loops are different from traditional C `for` loops, in that they can only be used with Iterators.

Here's an example of a for loop:

```    for( i in 0...a.length ) {
foo(a[i]);
}```

If the iterator was created with `...` operator, with its second term smaller than or equal to the first, then the loop will not execute.
If the `...` operator is used as above (inline, inside the for), then a smaller second term will give a compiler error, explaining the problem.

# Return

In order to exit from a function before the end or to return a value from a function, you can use the `return` expression :

```    function odd( x : Int ) : Bool {
if( x % 2 != 0 )
return true;
return false;
}```

The `return` expression can be used without an argument if the function does not require a value to be returned :

```    function foo() : Void {
// ...
if( abort )
return;
// ....
}```

# Break and Continue

These two keywords are useful to exit early a `for` or `while` loop or to go to the next iteration of a loop :

```    var i = 0;
while( i < 10 ) {
if( i == 7 )
continue; // skip this iteration.
// do not execute any more statements in this block,
// BUT go back to evaluating the "while" condition.
if( flag )
break; // stop early.
// Jump out of the "while" loop, and continue
// execution with the statement following the while loop.
}```

# Exceptions

Exceptions are a way to do non-local jumps. You can `throw` an exception and `catch` it from any calling function on the stack :

```    function foo() {
// ...
throw "invalid foo";
}

// ...

try {
foo();
} catch( e : String ) {
// handle exception
}```

There can be several `catch` blocks after a `try`, in order to catch different types of exceptions. They're tested in the order they're declared. Catching `Dynamic` will catch all exceptions :

```    try {
foo();
} catch( e : String ) {
// handle this kind of error
} catch( e : Error ) {
// handle another kind of error
} catch( e : Dynamic ) {
// handle all other errors
}```

All the `try` and the `catch` expressions must have the same return type except when no value is needed (same as `if`).

# Switch

Switches are a way to express multiple `if...else if... else if` test on the same value:

```    if( v == 0 )
e1
else if( v == foo(1) )
e2
else if( v == 65 || v == 90 )
e3
else
e4;```

Will translate to the following `switch` :

```    switch( v ) {
case 0:
e1;
case foo(1):
e2;
case 65, 90:
e3;
default:
e4;
}```

Note: In the example above, a case statement reads "65, 90". This is an example where a case expects to match either of the two (or several) values, listed as delimited by comma(s).

Switches in Haxe are different from traditional switches : all cases are separate expressions so after one case expression is executed the switch block is automatically exited. As a consequence, `break` can't be used in a `switch` and the position of the `default` case is not important.

On some platforms, switches on constant values (especially constant integers) might be optimized for better speed.

Switches can also be used on `enums` with different semantics. It will be explained later in this document.

# Local Functions

Local functions are declared using the `function` keyword, but they can't have a name. They're values just like literal integers or strings :

```    var f = function() { /* ... */ };
f(); // call the function```

Local functions can access their parameters, the current class statics and also the local variables that were declared before it :

```    var x = 10;
var add = function(n) { x += n; };
// now x is 15```

However, local functions declared in methods cannot access the `this` value. To access "this", you need to declare a local variable such as `me` :

```    class C {

var x : Int;

function f() {
// WILL NOT COMPILE
var add = function(n) { this.x += n; };
}

function f2() {

// will compile
var me = this;
var add = function(n) { me.x += n; };
}
}```

# Anonymous Objects

Anonymous objects can be declared using the following syntax :

`    var o = { age : 26, name : "Tom" };`

Please note that because of type inference, anonymous objects are also strictly typed.

version #19683, modified 2013-08-22 23:41:08 by tarwin