## Region Allocation

• You can create a new object on the heap using one of a few kinds of expression: `new` expr evaluates expr, places the result into the heap, and returns a pointer to the result. It is roughly equivalent to

``````t @ temp = malloc(sizeof(t));
// where t is the type of expr
*temp = _ expr_;
``````

For example, `new 17` allocates space for an integer on the heap, initializes it to 17, and returns a pointer to the space. For another example, if we have declared

``````struct Pair { int x; int y; };
``````

then `new Pair(7,9)` allocates space for two integers on the heap, initializes the first to 7 and the second to 9, and returns a pointer to the first.

• `new` array-initializer allocates space for an array, initializes it according to array-initializer, and returns a pointer to the first element. For example,

``````let x = new { 3, 4, 5 };
``````

declares a new array containing 3, 4, and 5, and initializes `x` to point to the first element. More interestingly,

``````new { for _ identifier_ < _ expr_1 : _ expr_2 }
``````

is roughly equivalent to

``````unsigned int sz = _ expr_1;
t @ temp = malloc(sz * sizeof(t2)); // where t is the  type of expr
for (int _ identifier_ = 0; _ identifier_ < sz; _ identifier_++)
temp[_ identifier_] = _ expr_2;
``````

That is, expr1 is evaluated first to get the size of the new array, the array is allocated, and each element of the array is initialized by the result of evaluating expr2. expr2 may use identifier, which holds the index of the element currently being initialized.

For example, this function returns an array containing the first n positive even numbers:

``````int *@fat n_evens(int n) {
return new {for next < n :  2*(next+1)};
}
``````

Note that:

• expr1 is evaluated exactly once, while expr2 is evaluated expr1 times.
• expr1 might evaluate to 0.
• expr1 might evaluate to a negative number. If so, it is implicitly converted to a very large unsigned integer; the allocation is likely to fail due to insufficient memory. Currently, this will cause a crash!!
• Currently, for array initializers are the only way to create an object whose size depends on run-time data.
• `malloc(sizeof(`type`))`. Returns a `@notnull` pointer to an uninitialized value of type type.

• `malloc(n*sizeof(`type`))` or `malloc(sizeof(`type`)*n)`. The type must be a bits-only type (i.e., cannot contain pointers, tagged unions, zero-terminated values, etc.) If `n` is a compile-time constant expression, returns a `@thin` pointer with `@numelts(n)`. If `n` is not a compile-time constant, returns a `@fat` pointer to the sequence of `n` uninitialized values.

• `calloc(n,sizeof(`type`))`. Similar to the `malloc` case above, but returns memory that is zero’d. Therefore, `calloc` supports types that are bits-only or zero-terminated.

• `malloc(e)` where `e` is an expression not of one of the above forms. If `e` is constant, returns a `char *@numelts(e)@nozeroterm` otherwise returns a char `*@fat@nozeroterm`.

Objects within regions can be created using the following analogous expressions.

• `rnew(`identifier`)` expr
• `rnew(`identifier`)` array-initializer
• `rmalloc(`identifier`,sizeof(`type`))`
• `rmalloc(`identifier,`n*sizeof(`type`))`
• `rmalloc(`identifier`,sizeof(`type`)*n)`
• `rmalloc(`identifier`,e))`
• `rcalloc(`identifier`,n,sizeof(`type`))`

Note that `new`, `malloc`, `calloc`, `rnew`, `rmalloc` and `rcalloc` are keywords.

Here, the first argument specifies a region handle. The Cyclone library has a global variable Core::heap_region which is a handle for the heap region. So, for example, rnew (heap_region) expr allocates memory in the heap region which is initialized with expr. Moreover, new expr can be replaced with rnew(heap_region) expr.

The only way to create an object in a stack region is declaring it as a local variable. Cyclone does not currently support `salloc`; use a lexical region instead.