Browse Source

Pull from upstream/master

Filippo Costa 8 years ago
parent
commit
53922aa8c5

+ 2 - 2
docs/api.html

@@ -79,7 +79,7 @@
          	<h1 class="section-header">API</h1><hr>
          	<h1 class="section-header">API</h1><hr>
 
 
 			<p class="section-content">
 			<p class="section-content">
-				Gravity can be extended at runtime using C API. The right step to proceed is usually to create a new class, then add methods and proporties to it and finally register that class inside the VM.
+				Gravity can be extended at runtime using C API. The right step to proceed is usually to create a new class, then add methods and properties to it and finally register that class inside the VM.
 			</p>
 			</p>
 			<pre><code class="cpp">
 			<pre><code class="cpp">
 	// report error callback function
 	// report error callback function
@@ -89,7 +89,7 @@
 		exit(0);
 		exit(0);
 	}
 	}
 
 
-	// function to be execute inside Gravity VM
+	// function to be executed inside Gravity VM
 	bool my_function (gravity_vm *vm, gravity_value_t *args,
 	bool my_function (gravity_vm *vm, gravity_value_t *args,
 	                  uint16_t nargs, uint32_t rindex) {
 	                  uint16_t nargs, uint32_t rindex) {
 		// do something useful here
 		// do something useful here

+ 3 - 3
docs/classes.html

@@ -94,7 +94,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Methods</h4>
 			<h4 class="section-h4">Methods</h4>
-			<p>Functions declared inside a class are called methods and are used to add behaviors to objects that belongs to a specific class:</p>
+			<p>Functions declared inside a class are called methods and are used to add behaviors to objects that belong to a specific class:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	class Italy {
 	class Italy {
 		func print() {
 		func print() {
@@ -104,7 +104,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Properties</h4>
 			<h4 class="section-h4">Properties</h4>
-			<p>Variables declared inside a class are called properties and are used to add states to objects that belongs to a specific class:</p>
+			<p>Variables declared inside a class are called properties and are used to add states to objects that belong to a specific class:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	class Italy {
 	class Italy {
 		var population = 60656000;
 		var population = 60656000;
@@ -221,7 +221,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Access specifiers</h4>
 			<h4 class="section-h4">Access specifiers</h4>
-			<p>The public and private keywords can be used to restrict access to specific part of code.</p>
+			<p>The public and private keywords can be used to restrict access to specific parts of code.</p>
 
 
          	</div>
          	</div>
        	</div> <!-- /row -->
        	</div> <!-- /row -->

+ 1 - 1
docs/enum.html

@@ -77,7 +77,7 @@
          	<h1 class="section-header">Enum</h1><hr>
          	<h1 class="section-header">Enum</h1><hr>
 
 
 			<p class="section-content">
 			<p class="section-content">
-			Enums defines a common type for a group of related values, if you are familiar with C, you will know that C enumerations assign related names to a set of integer values, enum in Gravity are much more flexible and enables you to assign even non integer values:
+			Enums defines a common type for a group of related values. If you are familiar with C, you will know that C enumerations assign related names to a set of integer values. Enums in Gravity are much more flexible and enable you to assign even non integer values:
 			</p>
 			</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	enum state {
 	enum state {

+ 4 - 4
docs/lists.html

@@ -77,7 +77,7 @@
          	<h1 class="section-header">List</h1><hr>
          	<h1 class="section-header">List</h1><hr>
 
 
 			<p class="section-content">
 			<p class="section-content">
-			Lists (or arrays) are simple sequence of objects, their size is dynamic and their index starts always from 0. They provide fast random access to their elements. You can create a list by placing a sequence of comma-separated expressions inside square brackets:
+			Lists (or arrays) are simple sequence of objects, their size is dynamic and their index starts always at 0. They provide fast random access to their elements. You can create a list by placing a sequence of comma-separated expressions inside square brackets:
 			</p>
 			</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var r = [1, 2, "Hello", 3.1415, true];
 	var r = [1, 2, "Hello", 3.1415, true];
@@ -87,7 +87,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Accessing elements</h4>
 			<h4 class="section-h4">Accessing elements</h4>
-			<p>You can access an element from a list by calling the subscript operator [] on it with the index of the element you want. Like most languages, indices start at zero:
+			<p>You can access an element from a list by calling the subscript operator [] on it with the index of the element you want. Like most languages, indices start at 0:
 			</p>
 			</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var names = ["Mark", "Andrew", "Paul", "Ross", "Frank", "Max"];
 	var names = ["Mark", "Andrew", "Paul", "Ross", "Frank", "Max"];
@@ -95,7 +95,7 @@
 	names[2];	// "Paul"
 	names[2];	// "Paul"
 			</code></pre>
 			</code></pre>
 
 
-			<p>Negative indices counts backwards from the end:</p>
+			<p>Negative indices count backwards from the end:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var names = ["Mark", "Andrew", "Paul", "Ross", "Frank", "Max"];
 	var names = ["Mark", "Andrew", "Paul", "Ross", "Frank", "Max"];
 	names[-1];	// "Max"
 	names[-1];	// "Max"
@@ -128,7 +128,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">List Contains</h4>
 			<h4 class="section-h4">List Contains</h4>
-			<p>The List class implements the contains methods as a convenient way to check for the existance of a value in a list:</p>
+			<p>The List class implements the contains methods as a convenient way to check for the existence of a value in a list:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var list = [1, 2, "Hello", 3.1415, true];
 	var list = [1, 2, "Hello", 3.1415, true];
 	return list.contains(3.1415); // Returns: true
 	return list.contains(3.1415); // Returns: true

+ 3 - 3
docs/loops.html

@@ -79,7 +79,7 @@
 			<p class="section-content">
 			<p class="section-content">
 
 
 			<h4 class="section-h4">While loop</h4>
 			<h4 class="section-h4">While loop</h4>
-			<p>A while loop performs a set of statements until a condition becomes false. These kinds of loops are best used when the number of iterations is not known before the first iteration begins.</p>
+			<p>A while loop performs a set of statements until a condition becomes false. These kind of loops are best used when the number of iterations is not known before the first iteration begins.</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	func main() {
 	func main() {
 		var i = 0;
 		var i = 0;
@@ -108,7 +108,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">For loop</h4>
 			<h4 class="section-h4">For loop</h4>
-			<p>You can access an element from a list by calling the subscript operator [] on it with the index of the element you want. Like most languages, indices start at zero:</p>
+			<p>You can access an element from a list by calling the subscript operator [] on it with the index of the element you want. As in most languages, indices start at zero:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var count = 0;
 	var count = 0;
 	for (var i in 0...40) {
 	for (var i in 0...40) {
@@ -180,7 +180,7 @@
                 System.print(vowels)  // aeiou
                 System.print(vowels)  // aeiou
         }
         }
 			</code></pre>
 			</code></pre>
-			<p>Loop within a <a href="maps.html">Map</a> where key is passed as closure argument (please note that key order is not preserved):</p>
+			<p>Loop within a <a href="maps.html">Map</a> where the key is passed as closure argument (please note that key order is not preserved):</p>
          	<pre><code class="swift">
          	<pre><code class="swift">
 	func main() {
 	func main() {
 		var target = ["key1":10,"key2":20,"key3":30,"key4":40];
 		var target = ["key1":10,"key2":20,"key3":30,"key4":40];

+ 3 - 3
docs/syntax.html

@@ -125,8 +125,8 @@
 	*/</code></pre>
 	*/</code></pre>
 			<p>While Gravity uses C-Style comments, Gravity still supports the common
 			<p>While Gravity uses C-Style comments, Gravity still supports the common
 			"#!" shebang to tell your shell what program to execute the file with.
 			"#!" shebang to tell your shell what program to execute the file with.
-			The shebang must be on the first line of the file in order to use it in
-			this way however:</p>
+			However, the shebang must be on the first line of the file in order to use it in
+			this way:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	#!/path/to/gravity
 	#!/path/to/gravity
 
 
@@ -162,7 +162,7 @@
 
 
 			<!-- RESERVED KEYWORDS -->
 			<!-- RESERVED KEYWORDS -->
 			<h4 class="section-h4">Reserved Keywords</h4>
 			<h4 class="section-h4">Reserved Keywords</h4>
-			<p>Like many other programming languages Gravity has some reserved keywords that assumes a very specific meaning in the context of the source code:</p>
+			<p>Like many other programming languages Gravity has some reserved keywords that assume a very specific meaning in the context of the source code:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	if in or is for var and not func else true enum case null
 	if in or is for var and not func else true enum case null
 	file lazy super false break while class const event _func
 	file lazy super false break while class const event _func

+ 1 - 1
docs/system.html

@@ -92,7 +92,7 @@
 				</code></pre>
 				</code></pre>
 
 
 				<h4 class="section-h4">Garbage collector methods</h4>
 				<h4 class="section-h4">Garbage collector methods</h4>
-				<p>Gravity automatically manage memory for you using a tri-colour marking garbage collector, using the System class the user has the ability to change some of its settings and even disable it when certain performance critical tasks need to be performed:</p>
+				<p>Gravity automatically manages memory for you using a tri-colour marking garbage collector, using the System class the user has the ability to change some of its settings and even disable it when certain performance critical tasks need to be performed:</p>
 				<pre><code class="swift">
 				<pre><code class="swift">
 	func main() {
 	func main() {
 		// disable GC
 		// disable GC

+ 4 - 4
docs/types.html

@@ -84,7 +84,7 @@
 			<p>Object is the root class of every object inside Gravity. Through the Object class, objects inherit a basic interface to the runtime system and the ability to behave as Gravity objects.</p>
 			<p>Object is the root class of every object inside Gravity. Through the Object class, objects inherit a basic interface to the runtime system and the ability to behave as Gravity objects.</p>
 
 
 			<h4 class="section-h4">Int</h4>
 			<h4 class="section-h4">Int</h4>
-			<p>An Int represents a 64 bits (can optionally be compiled as 32bit) signed number:</p>
+			<p>An Int represents a 64 bit (can optionally be compiled as 32 bit) signed number:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var a = 123;		// decimal
 	var a = 123;		// decimal
 	var b = 0xFF;		// hexadecimal
 	var b = 0xFF;		// hexadecimal
@@ -98,7 +98,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Float</h4>
 			<h4 class="section-h4">Float</h4>
-			<p>A float represents a 32 bits (or better) floating point number:</p>
+			<p>A float represents a 32 bit (or better) floating point number:</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var a = 3.1415;		// float
 	var a = 3.1415;		// float
 	var b = 1.25e2;		// scientific notation
 	var b = 1.25e2;		// scientific notation
@@ -108,7 +108,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">String</h4>
 			<h4 class="section-h4">String</h4>
-			<p>Strings are an immutable sequence of characters. String literals can be surrounded in double or single quotes.</p>
+			<p>Strings are an immutable sequence of characters. String literals can be surrounded with double or single quotes.</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var a = "Hello World";  // double quotes
 	var a = "Hello World";  // double quotes
 	var b = 'Hello World';  // single quotes
 	var b = 'Hello World';  // single quotes
@@ -152,7 +152,7 @@
 			</code></pre>
 			</code></pre>
 
 
 			<h4 class="section-h4">Bool</h4>
 			<h4 class="section-h4">Bool</h4>
-			<p>The bool data type can have only two values, they are the literals true and false. A Bool value expresses the validity of a condition (tells whether the condition is true or false).</p>
+			<p>The Bool data type can have only two values, they are the literals true and false. A Bool value expresses the validity of a condition (tells whether the condition is true or false).</p>
 			<pre><code class="swift">
 			<pre><code class="swift">
 	var a = true;
 	var a = true;
 	var b = false;
 	var b = false;

+ 1 - 1
src/cli/gravity.c

@@ -213,7 +213,7 @@ int main (int argc, const char* argv[]) {
 
 
         // create closure to execute inline code
         // create closure to execute inline code
         if (type == OP_INLINE_RUN) {
         if (type == OP_INLINE_RUN) {
-            char *buffer = mem_alloc(size+1024);
+            char *buffer = mem_alloc(NULL, size+1024);
             assert(buffer);
             assert(buffer);
             size = snprintf(buffer, size+1024, "func main() {%s};", input_file);
             size = snprintf(buffer, size+1024, "func main() {%s};", input_file);
             source_code = buffer;
             source_code = buffer;

+ 60 - 60
src/compiler/gravity_ast.c

@@ -20,19 +20,19 @@
 // MARK: -
 // MARK: -
 
 
 void_r *void_array_create (void) {
 void_r *void_array_create (void) {
-	void_r *r = mem_alloc(sizeof(void_r));
+	void_r *r = mem_alloc(NULL, sizeof(void_r));
 	marray_init(*r);
 	marray_init(*r);
 	return r;
 	return r;
 }
 }
 
 
 cstring_r *cstring_array_create (void) {
 cstring_r *cstring_array_create (void) {
-	cstring_r *r = mem_alloc(sizeof(cstring_r));
+	cstring_r *r = mem_alloc(NULL, sizeof(cstring_r));
 	gnode_array_init(r);
 	gnode_array_init(r);
 	return r;
 	return r;
 }
 }
 
 
 gnode_r *gnode_array_create (void) {
 gnode_r *gnode_array_create (void) {
-	gnode_r *r = mem_alloc(sizeof(gnode_r));
+	gnode_r *r = mem_alloc(NULL, sizeof(gnode_r));
 	gnode_array_init(r);
 	gnode_array_init(r);
 	return r;
 	return r;
 }
 }
@@ -73,7 +73,7 @@ gnode_r *gnode_array_remove_byindex(gnode_r *old_list, size_t index) {
 gupvalue_t *gnode_function_add_upvalue(gnode_function_decl_t *f, gnode_var_t *symbol, uint16_t n) {
 gupvalue_t *gnode_function_add_upvalue(gnode_function_decl_t *f, gnode_var_t *symbol, uint16_t n) {
 	// create uplist if necessary
 	// create uplist if necessary
 	if (!f->uplist) {
 	if (!f->uplist) {
-		f->uplist = mem_alloc(sizeof(gupvalue_r));
+		f->uplist = mem_alloc(NULL, sizeof(gupvalue_r));
 		gnode_array_init(f->uplist);
 		gnode_array_init(f->uplist);
 	}
 	}
 
 
@@ -85,7 +85,7 @@ gupvalue_t *gnode_function_add_upvalue(gnode_function_decl_t *f, gnode_var_t *sy
 	}, gupvalue_t *);
 	}, gupvalue_t *);
 
 
 	// symbol not found in uplist so add it
 	// symbol not found in uplist so add it
-	gupvalue_t *upvalue = mem_alloc(sizeof(gupvalue_t));
+	gupvalue_t *upvalue = mem_alloc(NULL, sizeof(gupvalue_t));
 	upvalue->node = (gnode_t *)symbol;
 	upvalue->node = (gnode_t *)symbol;
 	upvalue->index = (n == 1) ? symbol->index : (uint32_t)gnode_array_size(f->uplist);
 	upvalue->index = (n == 1) ? symbol->index : (uint32_t)gnode_array_size(f->uplist);
 	upvalue->selfindex = (uint32_t)gnode_array_size(f->uplist);
 	upvalue->selfindex = (uint32_t)gnode_array_size(f->uplist);
@@ -99,7 +99,7 @@ gupvalue_t *gnode_function_add_upvalue(gnode_function_decl_t *f, gnode_var_t *sy
 // MARK: - Statements initializers -
 // MARK: - Statements initializers -
 
 
 gnode_t *gnode_jump_stat_create (gtoken_s token, gnode_t *expr, gnode_t *decl) {
 gnode_t *gnode_jump_stat_create (gtoken_s token, gnode_t *expr, gnode_t *decl) {
-	gnode_jump_stmt_t *node = (gnode_jump_stmt_t *)mem_alloc(sizeof(gnode_jump_stmt_t));
+	gnode_jump_stmt_t *node = (gnode_jump_stmt_t *)mem_alloc(NULL, sizeof(gnode_jump_stmt_t));
 
 
 	SETBASE(node, NODE_JUMP_STAT, token, NULL);
 	SETBASE(node, NODE_JUMP_STAT, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -108,7 +108,7 @@ gnode_t *gnode_jump_stat_create (gtoken_s token, gnode_t *expr, gnode_t *decl) {
 }
 }
 
 
 gnode_t *gnode_label_stat_create (gtoken_s token, gnode_t *expr, gnode_t *stmt, gnode_t *decl) {
 gnode_t *gnode_label_stat_create (gtoken_s token, gnode_t *expr, gnode_t *stmt, gnode_t *decl) {
-	gnode_label_stmt_t *node = (gnode_label_stmt_t *)mem_alloc(sizeof(gnode_label_stmt_t));
+	gnode_label_stmt_t *node = (gnode_label_stmt_t *)mem_alloc(NULL, sizeof(gnode_label_stmt_t));
 
 
 	SETBASE(node, NODE_LABEL_STAT, token, NULL);
 	SETBASE(node, NODE_LABEL_STAT, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -118,7 +118,7 @@ gnode_t *gnode_label_stat_create (gtoken_s token, gnode_t *expr, gnode_t *stmt,
 }
 }
 
 
 gnode_t *gnode_flow_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt1, gnode_t *stmt2, gnode_t *decl) {
 gnode_t *gnode_flow_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt1, gnode_t *stmt2, gnode_t *decl) {
-	gnode_flow_stmt_t *node = (gnode_flow_stmt_t *)mem_alloc(sizeof(gnode_flow_stmt_t));
+	gnode_flow_stmt_t *node = (gnode_flow_stmt_t *)mem_alloc(NULL, sizeof(gnode_flow_stmt_t));
 
 
 	SETBASE(node, NODE_FLOW_STAT, token, NULL);
 	SETBASE(node, NODE_FLOW_STAT, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -129,7 +129,7 @@ gnode_t *gnode_flow_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt1,
 }
 }
 
 
 gnode_t *gnode_loop_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt, gnode_t *expr, gnode_t *decl) {
 gnode_t *gnode_loop_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt, gnode_t *expr, gnode_t *decl) {
-	gnode_loop_stmt_t *node = (gnode_loop_stmt_t *)mem_alloc(sizeof(gnode_loop_stmt_t));
+	gnode_loop_stmt_t *node = (gnode_loop_stmt_t *)mem_alloc(NULL, sizeof(gnode_loop_stmt_t));
 
 
 	SETBASE(node, NODE_LOOP_STAT, token, NULL);
 	SETBASE(node, NODE_LOOP_STAT, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -141,7 +141,7 @@ gnode_t *gnode_loop_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt, g
 }
 }
 
 
 gnode_t *gnode_block_stat_create (gnode_n type, gtoken_s token, gnode_r *stmts, gnode_t *decl) {
 gnode_t *gnode_block_stat_create (gnode_n type, gtoken_s token, gnode_r *stmts, gnode_t *decl) {
-	gnode_compound_stmt_t *node = (gnode_compound_stmt_t *)mem_alloc(sizeof(gnode_compound_stmt_t));
+	gnode_compound_stmt_t *node = (gnode_compound_stmt_t *)mem_alloc(NULL, sizeof(gnode_compound_stmt_t));
 
 
 	SETBASE(node, type, token, NULL);
 	SETBASE(node, type, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -151,7 +151,7 @@ gnode_t *gnode_block_stat_create (gnode_n type, gtoken_s token, gnode_r *stmts,
 }
 }
 
 
 gnode_t *gnode_empty_stat_create (gtoken_s token, gnode_t *decl) {
 gnode_t *gnode_empty_stat_create (gtoken_s token, gnode_t *decl) {
-	gnode_empty_stmt_t *node = (gnode_empty_stmt_t *)mem_alloc(sizeof(gnode_empty_stmt_t));
+	gnode_empty_stmt_t *node = (gnode_empty_stmt_t *)mem_alloc(NULL, sizeof(gnode_empty_stmt_t));
 
 
 	SETBASE(node, NODE_EMPTY_STAT, token, NULL);
 	SETBASE(node, NODE_EMPTY_STAT, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -161,7 +161,7 @@ gnode_t *gnode_empty_stat_create (gtoken_s token, gnode_t *decl) {
 // MARK: - Declarations initializers -
 // MARK: - Declarations initializers -
 
 
 gnode_t *gnode_class_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_t *superclass, gnode_r *protocols, gnode_r *declarations, bool is_struct, void *meta, gnode_t *decl) {
 gnode_t *gnode_class_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_t *superclass, gnode_r *protocols, gnode_r *declarations, bool is_struct, void *meta, gnode_t *decl) {
-	gnode_class_decl_t *node = (gnode_class_decl_t *)mem_alloc(sizeof(gnode_class_decl_t));
+	gnode_class_decl_t *node = (gnode_class_decl_t *)mem_alloc(NULL, sizeof(gnode_class_decl_t));
 	node->is_struct = is_struct;
 	node->is_struct = is_struct;
 
 
 	SETBASE(node, NODE_CLASS_DECL, token, meta);
 	SETBASE(node, NODE_CLASS_DECL, token, meta);
@@ -180,7 +180,7 @@ gnode_t *gnode_class_decl_create (gtoken_s token, const char *identifier, gtoken
 }
 }
 
 
 gnode_t *gnode_module_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations, void *meta, gnode_t *decl) {
 gnode_t *gnode_module_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations, void *meta, gnode_t *decl) {
-	gnode_module_decl_t *node = (gnode_module_decl_t *)mem_alloc(sizeof(gnode_module_decl_t));
+	gnode_module_decl_t *node = (gnode_module_decl_t *)mem_alloc(NULL, sizeof(gnode_module_decl_t));
 
 
 	SETBASE(node, NODE_MODULE_DECL, token, meta);
 	SETBASE(node, NODE_MODULE_DECL, token, meta);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -193,7 +193,7 @@ gnode_t *gnode_module_decl_create (gtoken_s token, const char *identifier, gtoke
 }
 }
 
 
 gnode_t *gnode_enum_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, symboltable_t *symtable, void *meta, gnode_t *decl) {
 gnode_t *gnode_enum_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, symboltable_t *symtable, void *meta, gnode_t *decl) {
-	gnode_enum_decl_t *node = (gnode_enum_decl_t *)mem_alloc(sizeof(gnode_enum_decl_t));
+	gnode_enum_decl_t *node = (gnode_enum_decl_t *)mem_alloc(NULL, sizeof(gnode_enum_decl_t));
 
 
 	SETBASE(node, NODE_ENUM_DECL, token, meta);
 	SETBASE(node, NODE_ENUM_DECL, token, meta);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -206,7 +206,7 @@ gnode_t *gnode_enum_decl_create (gtoken_s token, const char *identifier, gtoken_
 }
 }
 
 
 gnode_t *gnode_function_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *params, gnode_compound_stmt_t *block, void *meta, gnode_t *decl) {
 gnode_t *gnode_function_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *params, gnode_compound_stmt_t *block, void *meta, gnode_t *decl) {
-	gnode_function_decl_t *node = (gnode_function_decl_t *)mem_alloc(sizeof(gnode_function_decl_t));
+	gnode_function_decl_t *node = (gnode_function_decl_t *)mem_alloc(NULL, sizeof(gnode_function_decl_t));
 
 
 	SETBASE(node, NODE_FUNCTION_DECL, token, meta);
 	SETBASE(node, NODE_FUNCTION_DECL, token, meta);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -222,7 +222,7 @@ gnode_t *gnode_function_decl_create (gtoken_s token, const char *identifier, gto
 }
 }
 
 
 gnode_t *gnode_variable_decl_create (gtoken_s token, gtoken_t type, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations, void *meta, gnode_t *decl) {
 gnode_t *gnode_variable_decl_create (gtoken_s token, gtoken_t type, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations, void *meta, gnode_t *decl) {
-	gnode_variable_decl_t *node = (gnode_variable_decl_t *)mem_alloc(sizeof(gnode_variable_decl_t));
+	gnode_variable_decl_t *node = (gnode_variable_decl_t *)mem_alloc(NULL, sizeof(gnode_variable_decl_t));
 
 
 	SETBASE(node, NODE_VARIABLE_DECL, token, meta);
 	SETBASE(node, NODE_VARIABLE_DECL, token, meta);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -235,7 +235,7 @@ gnode_t *gnode_variable_decl_create (gtoken_s token, gtoken_t type, gtoken_t acc
 }
 }
 
 
 gnode_t *gnode_variable_create (gtoken_s token, const char *identifier, const char *annotation_type, gtoken_t access_specifier, gnode_t *expr, gnode_t *decl) {
 gnode_t *gnode_variable_create (gtoken_s token, const char *identifier, const char *annotation_type, gtoken_t access_specifier, gnode_t *expr, gnode_t *decl) {
-	gnode_var_t *node = (gnode_var_t *)mem_alloc(sizeof(gnode_var_t));
+	gnode_var_t *node = (gnode_var_t *)mem_alloc(NULL, sizeof(gnode_var_t));
 
 
 	SETBASE(node, NODE_VARIABLE, token, NULL);
 	SETBASE(node, NODE_VARIABLE, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -298,7 +298,7 @@ bool gnode_is_literal_number (gnode_t *node) {
 gnode_t *gnode_binary_expr_create (gtoken_t op, gnode_t *left, gnode_t *right, gnode_t *decl) {
 gnode_t *gnode_binary_expr_create (gtoken_t op, gnode_t *left, gnode_t *right, gnode_t *decl) {
 	if (!left || !right) return NULL;
 	if (!left || !right) return NULL;
 
 
-	gnode_binary_expr_t	*node = (gnode_binary_expr_t *)mem_alloc(sizeof(gnode_binary_expr_t));
+	gnode_binary_expr_t	*node = (gnode_binary_expr_t *)mem_alloc(NULL, sizeof(gnode_binary_expr_t));
 	SETBASE(node, NODE_BINARY_EXPR, left->token, NULL);
 	SETBASE(node, NODE_BINARY_EXPR, left->token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
 	node->op = op;
 	node->op = op;
@@ -310,7 +310,7 @@ gnode_t *gnode_binary_expr_create (gtoken_t op, gnode_t *left, gnode_t *right, g
 gnode_t *gnode_unary_expr_create (gtoken_t op, gnode_t *expr, gnode_t *decl) {
 gnode_t *gnode_unary_expr_create (gtoken_t op, gnode_t *expr, gnode_t *decl) {
 	if (!expr) return NULL;
 	if (!expr) return NULL;
 
 
-	gnode_unary_expr_t *node = (gnode_unary_expr_t *)mem_alloc(sizeof(gnode_unary_expr_t));
+	gnode_unary_expr_t *node = (gnode_unary_expr_t *)mem_alloc(NULL, sizeof(gnode_unary_expr_t));
 	SETBASE(node, NODE_UNARY_EXPR, expr->token, NULL);
 	SETBASE(node, NODE_UNARY_EXPR, expr->token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
 	node->op = op;
 	node->op = op;
@@ -321,7 +321,7 @@ gnode_t *gnode_unary_expr_create (gtoken_t op, gnode_t *expr, gnode_t *decl) {
 gnode_t *gnode_file_expr_create (gtoken_s token, cstring_r *list, gnode_t *decl) {
 gnode_t *gnode_file_expr_create (gtoken_s token, cstring_r *list, gnode_t *decl) {
 	if (!list) return NULL;
 	if (!list) return NULL;
 
 
-	gnode_file_expr_t *node = (gnode_file_expr_t *)mem_alloc(sizeof(gnode_file_expr_t));
+	gnode_file_expr_t *node = (gnode_file_expr_t *)mem_alloc(NULL, sizeof(gnode_file_expr_t));
 	SETBASE(node, NODE_FILE_EXPR, token, NULL);
 	SETBASE(node, NODE_FILE_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
 	node->identifiers = list;
 	node->identifiers = list;
@@ -331,7 +331,7 @@ gnode_t *gnode_file_expr_create (gtoken_s token, cstring_r *list, gnode_t *decl)
 gnode_t *gnode_identifier_expr_create (gtoken_s token, const char *identifier, const char *identifier2, gnode_t *decl) {
 gnode_t *gnode_identifier_expr_create (gtoken_s token, const char *identifier, const char *identifier2, gnode_t *decl) {
 	if (!identifier) return NULL;
 	if (!identifier) return NULL;
 
 
-	gnode_identifier_expr_t *node = (gnode_identifier_expr_t *)mem_alloc(sizeof(gnode_identifier_expr_t));
+	gnode_identifier_expr_t *node = (gnode_identifier_expr_t *)mem_alloc(NULL, sizeof(gnode_identifier_expr_t));
 	SETBASE(node, NODE_IDENTIFIER_EXPR, token, NULL);
 	SETBASE(node, NODE_IDENTIFIER_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
 	node->value = identifier;
 	node->value = identifier;
@@ -351,7 +351,7 @@ void gnode_literal_dump (gnode_literal_expr_t *node, char *buffer, int buffersiz
 }
 }
 
 
 static gnode_t *gnode_literal_value_expr_create (gtoken_s token, gliteral_t type, const char *s, double d, int64_t n64, gnode_t *decl) {
 static gnode_t *gnode_literal_value_expr_create (gtoken_s token, gliteral_t type, const char *s, double d, int64_t n64, gnode_t *decl) {
-	gnode_literal_expr_t *node = (gnode_literal_expr_t *)mem_alloc(sizeof(gnode_literal_expr_t));
+	gnode_literal_expr_t *node = (gnode_literal_expr_t *)mem_alloc(NULL, sizeof(gnode_literal_expr_t));
 
 
 	SETBASE(node, NODE_LITERAL_EXPR, token, NULL);
 	SETBASE(node, NODE_LITERAL_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -379,11 +379,11 @@ gnode_t *gnode_string_interpolation_create (gtoken_s token, gnode_r *r, gnode_t
 gnode_t *gnode_literal_string_expr_create (gtoken_s token, char *s, uint32_t len, bool allocated, gnode_t *decl) {
 gnode_t *gnode_literal_string_expr_create (gtoken_s token, char *s, uint32_t len, bool allocated, gnode_t *decl) {
 	gnode_literal_expr_t *node = (gnode_literal_expr_t *)gnode_literal_value_expr_create(token, LITERAL_STRING, NULL, 0, 0, decl);
 	gnode_literal_expr_t *node = (gnode_literal_expr_t *)gnode_literal_value_expr_create(token, LITERAL_STRING, NULL, 0, 0, decl);
 
 
-		node->len = len;
+	node->len = len;
 	if (allocated) {
 	if (allocated) {
 		node->value.str = s;
 		node->value.str = s;
 	} else {
 	} else {
-		node->value.str = (char *)mem_alloc(len+1);
+		node->value.str = (char *)mem_alloc(NULL, len+1);
 		memcpy((void *)node->value.str, (const void *)s, len);
 		memcpy((void *)node->value.str, (const void *)s, len);
 	}
 	}
 
 
@@ -403,7 +403,7 @@ gnode_t *gnode_literal_bool_expr_create (gtoken_s token, int32_t n, gnode_t *dec
 }
 }
 
 
 gnode_t *gnode_keyword_expr_create (gtoken_s token, gnode_t *decl) {
 gnode_t *gnode_keyword_expr_create (gtoken_s token, gnode_t *decl) {
-	gnode_keyword_expr_t *node = (gnode_keyword_expr_t *)mem_alloc(sizeof(gnode_keyword_expr_t));
+	gnode_keyword_expr_t *node = (gnode_keyword_expr_t *)mem_alloc(NULL, sizeof(gnode_keyword_expr_t));
 
 
 	SETBASE(node, NODE_KEYWORD_EXPR, token, NULL);
 	SETBASE(node, NODE_KEYWORD_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -411,7 +411,7 @@ gnode_t *gnode_keyword_expr_create (gtoken_s token, gnode_t *decl) {
 }
 }
 
 
 gnode_t *gnode_postfix_subexpr_create (gtoken_s token, gnode_n type, gnode_t *expr, gnode_r *list, gnode_t *decl) {
 gnode_t *gnode_postfix_subexpr_create (gtoken_s token, gnode_n type, gnode_t *expr, gnode_r *list, gnode_t *decl) {
-	gnode_postfix_subexpr_t *node = (gnode_postfix_subexpr_t *)mem_alloc(sizeof(gnode_postfix_subexpr_t));
+	gnode_postfix_subexpr_t *node = (gnode_postfix_subexpr_t *)mem_alloc(NULL, sizeof(gnode_postfix_subexpr_t));
 
 
     SETBASE(node, type, token, NULL);
     SETBASE(node, type, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -423,17 +423,17 @@ gnode_t *gnode_postfix_subexpr_create (gtoken_s token, gnode_n type, gnode_t *ex
 }
 }
 
 
 gnode_t *gnode_postfix_expr_create (gtoken_s token, gnode_t *id, gnode_r *list, gnode_t *decl) {
 gnode_t *gnode_postfix_expr_create (gtoken_s token, gnode_t *id, gnode_r *list, gnode_t *decl) {
-	gnode_postfix_expr_t *node = (gnode_postfix_expr_t *)mem_alloc(sizeof(gnode_postfix_expr_t));
+	gnode_postfix_expr_t *node = (gnode_postfix_expr_t *)mem_alloc(NULL, sizeof(gnode_postfix_expr_t));
 
 
 	SETBASE(node, NODE_POSTFIX_EXPR, token, NULL);
 	SETBASE(node, NODE_POSTFIX_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
-	node->id = id;
-	node->list = list;
+    node->id = id;
+    node->list = list;
 	return (gnode_t *)node;
 	return (gnode_t *)node;
 }
 }
 
 
 gnode_t *gnode_list_expr_create (gtoken_s token, gnode_r *list1, gnode_r *list2, bool ismap, gnode_t *decl) {
 gnode_t *gnode_list_expr_create (gtoken_s token, gnode_r *list1, gnode_r *list2, bool ismap, gnode_t *decl) {
-	gnode_list_expr_t *node = (gnode_list_expr_t *)mem_alloc(sizeof(gnode_list_expr_t));
+	gnode_list_expr_t *node = (gnode_list_expr_t *)mem_alloc(NULL, sizeof(gnode_list_expr_t));
 
 
 	SETBASE(node, NODE_LIST_EXPR, token, NULL);
 	SETBASE(node, NODE_LIST_EXPR, token, NULL);
     SETDECL(node, decl);
     SETDECL(node, decl);
@@ -716,41 +716,41 @@ static void free_list_expr (gvisitor_t *self, gnode_list_expr_t *node) {
 // MARK: -
 // MARK: -
 
 
 void gnode_free (gnode_t *ast) {
 void gnode_free (gnode_t *ast) {
-	gvisitor_t visitor = {
-		.nerr = 0,
-		.data = NULL,
-		.delegate = NULL,
+    gvisitor_t visitor = {
+        .nerr = 0,
+        .data = NULL,
+        .delegate = NULL,
 
 
         // COMMON
         // COMMON
         .visit_pre = NULL,
         .visit_pre = NULL,
         .visit_post = NULL,
         .visit_post = NULL,
 
 
-		// STATEMENTS: 7
-		.visit_list_stmt = free_list_stmt,
-		.visit_compound_stmt = free_compound_stmt,
-		.visit_label_stmt = free_label_stmt,
-		.visit_flow_stmt = free_flow_stmt,
-		.visit_loop_stmt = free_loop_stmt,
-		.visit_jump_stmt = free_jump_stmt,
-		.visit_empty_stmt = free_empty_stmt,
-
-		// DECLARATIONS: 5
-		.visit_function_decl = free_function_decl,
-		.visit_variable_decl = free_variable_decl,
-		.visit_enum_decl = free_enum_decl,
-		.visit_class_decl = free_class_decl,
-		.visit_module_decl = free_module_decl,
-
-		// EXPRESSIONS: 7+1
-		.visit_binary_expr = free_binary_expr,
-		.visit_unary_expr = free_unary_expr,
-		.visit_file_expr = free_file_expr,
-		.visit_literal_expr = free_literal_expr,
-		.visit_identifier_expr = free_identifier_expr,
-		.visit_keyword_expr = free_keyword_expr,
-		.visit_list_expr = free_list_expr,
-		.visit_postfix_expr = free_postfix_expr
-	};
+        // STATEMENTS: 7
+        .visit_list_stmt = free_list_stmt,
+        .visit_compound_stmt = free_compound_stmt,
+        .visit_label_stmt = free_label_stmt,
+        .visit_flow_stmt = free_flow_stmt,
+        .visit_loop_stmt = free_loop_stmt,
+        .visit_jump_stmt = free_jump_stmt,
+        .visit_empty_stmt = free_empty_stmt,
+
+        // DECLARATIONS: 5
+        .visit_function_decl = free_function_decl,
+        .visit_variable_decl = free_variable_decl,
+        .visit_enum_decl = free_enum_decl,
+        .visit_class_decl = free_class_decl,
+        .visit_module_decl = free_module_decl,
+
+        // EXPRESSIONS: 7+1
+        .visit_binary_expr = free_binary_expr,
+        .visit_unary_expr = free_unary_expr,
+        .visit_file_expr = free_file_expr,
+        .visit_literal_expr = free_literal_expr,
+        .visit_identifier_expr = free_identifier_expr,
+        .visit_keyword_expr = free_keyword_expr,
+        .visit_list_expr = free_list_expr,
+        .visit_postfix_expr = free_postfix_expr
+    };
 
 
     gvisit(&visitor, ast);
     gvisit(&visitor, ast);
 }
 }

+ 1 - 1
src/compiler/gravity_compiler.c

@@ -68,7 +68,7 @@ static void internal_vm_cleanup (gravity_vm *vm) {
 // MARK: -
 // MARK: -
 
 
 gravity_compiler_t *gravity_compiler_create (gravity_delegate_t *delegate) {
 gravity_compiler_t *gravity_compiler_create (gravity_delegate_t *delegate) {
-	gravity_compiler_t *compiler = mem_alloc(sizeof(gravity_compiler_t));
+	gravity_compiler_t *compiler = mem_alloc(NULL, sizeof(gravity_compiler_t));
 	if (!compiler) return NULL;
 	if (!compiler) return NULL;
 
 
 	compiler->ast = NULL;
 	compiler->ast = NULL;

+ 5 - 5
src/compiler/gravity_ircode.c

@@ -32,14 +32,14 @@ struct ircode_t {
 };
 };
 
 
 ircode_t *ircode_create (uint16_t nlocals) {
 ircode_t *ircode_create (uint16_t nlocals) {
-	ircode_t *code = (ircode_t *)mem_alloc(sizeof(ircode_t));
+	ircode_t *code = (ircode_t *)mem_alloc(NULL, sizeof(ircode_t));
 	code->label_counter = 0;
 	code->label_counter = 0;
 	code->nlocals = nlocals;
 	code->nlocals = nlocals;
 	code->ntemps = 0;
 	code->ntemps = 0;
 	code->maxtemp = 0;
 	code->maxtemp = 0;
 	code->error = false;
 	code->error = false;
 
 
-	code->list = mem_alloc(sizeof(code_r));
+	code->list = mem_alloc(NULL, sizeof(code_r));
 	marray_init(*code->list);
 	marray_init(*code->list);
 	marray_init(code->label_true);
 	marray_init(code->label_true);
 	marray_init(code->label_false);
 	marray_init(code->label_false);
@@ -118,7 +118,7 @@ static inst_t *inst_new (opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3, opt
 	}
 	}
 	#endif
 	#endif
 
 
-	inst_t *inst = (inst_t *)mem_alloc(sizeof(inst_t));
+	inst_t *inst = (inst_t *)mem_alloc(NULL, sizeof(inst_t));
 	inst->op = op;
 	inst->op = op;
 	inst->tag = tag;
 	inst->tag = tag;
 	inst->p1 = p1;
 	inst->p1 = p1;
@@ -162,7 +162,7 @@ void ircode_patch_init (ircode_t *code, uint16_t index) {
 	ircode_register_pop(code);
 	ircode_register_pop(code);
 
 
 	// create new instruction list
 	// create new instruction list
-	code_r		*list = mem_alloc(sizeof(code_r));
+	code_r		*list = mem_alloc(NULL, sizeof(code_r));
 	marray_init(*list);
 	marray_init(*list);
 
 
 	// add newly create instructions
 	// add newly create instructions
@@ -410,7 +410,7 @@ static void dump_context(bool *context) {
 #endif
 #endif
 
 
 void ircode_push_context (ircode_t *code) {
 void ircode_push_context (ircode_t *code) {
-	bool *context = mem_alloc(sizeof(bool) * MAX_REGISTERS);
+	bool *context = mem_alloc(NULL, sizeof(bool) * MAX_REGISTERS);
 	marray_push(bool *, code->context, context);
 	marray_push(bool *, code->context, context);
 }
 }
 
 

+ 1 - 1
src/compiler/gravity_lexer.c

@@ -525,7 +525,7 @@ static gtoken_t lexer_scan_preprocessor(gravity_lexer_t *lexer) {
 // MARK: -
 // MARK: -
 
 
 gravity_lexer_t *gravity_lexer_create (const char *source, size_t len, uint32_t fileid, bool is_static) {
 gravity_lexer_t *gravity_lexer_create (const char *source, size_t len, uint32_t fileid, bool is_static) {
-	gravity_lexer_t *lexer = mem_alloc(sizeof(gravity_lexer_t));
+	gravity_lexer_t *lexer = mem_alloc(NULL, sizeof(gravity_lexer_t));
 	if (!lexer) return NULL;
 	if (!lexer) return NULL;
 	bzero(lexer, sizeof(gravity_lexer_t));
 	bzero(lexer, sizeof(gravity_lexer_t));
 
 

+ 1 - 1
src/compiler/gravity_optimizer.c

@@ -71,7 +71,7 @@ static void finalize_function (gravity_function_t *f) {
 
 
 	// +1 is just a trick so the VM switch loop terminates with an implicit RET0 instruction (RET0 has opcode 0)
 	// +1 is just a trick so the VM switch loop terminates with an implicit RET0 instruction (RET0 has opcode 0)
 	f->ninsts = ninst;
 	f->ninsts = ninst;
-	bytecode = (uint32_t *)mem_alloc((ninst+1) * sizeof(uint32_t));
+	bytecode = (uint32_t *)mem_alloc(NULL, (ninst+1) * sizeof(uint32_t));
 	assert(bytecode);
 	assert(bytecode);
 
 
 	uint32_t j=0;
 	uint32_t j=0;

+ 34 - 31
src/compiler/gravity_parser.c

@@ -72,13 +72,13 @@ typedef struct {
 } grammar_rule;
 } grammar_rule;
 
 
 // This table defines all of the parsing rules for the prefix and infix expressions in the grammar.
 // This table defines all of the parsing rules for the prefix and infix expressions in the grammar.
-#define RULE(prec, fn1, fn2)			(grammar_rule){ fn1, fn2, prec, NULL, false}
-#define PREFIX(prec, fn)				(grammar_rule){ fn, NULL, prec, NULL, false}
-#define INFIX(prec, fn)					(grammar_rule){ NULL, fn, prec, NULL, false}
-#define INFIX_OPERATOR(prec, name)		(grammar_rule){ NULL, parse_infix, prec, name, false}
-#define INFIX_OPERATOR_RIGHT(prec,name) (grammar_rule){ NULL, parse_infix, prec, name, true}
-#define PREFIX_OPERATOR(name)			(grammar_rule){ parse_unary, NULL, PREC_LOWEST, name, false}
-#define OPERATOR(prec, name)			(grammar_rule){ parse_unary, parse_infix, prec, name, false}
+#define RULE(prec, fn1, fn2)					(grammar_rule){ fn1, fn2, prec, NULL, false}
+#define PREFIX(prec, fn)						(grammar_rule){ fn, NULL, prec, NULL, false}
+#define INFIX(prec, fn)							(grammar_rule){ NULL, fn, prec, NULL, false}
+#define INFIX_OPERATOR(prec, name)				(grammar_rule){ NULL, parse_infix, prec, name, false}
+#define INFIX_OPERATOR_RIGHT(prec,name)			(grammar_rule){ NULL, parse_infix, prec, name, true}
+#define PREFIX_OPERATOR(name)					(grammar_rule){ parse_unary, NULL, PREC_LOWEST, name, false}
+#define OPERATOR(prec, name)					(grammar_rule){ parse_unary, parse_infix, prec, name, false}
 
 
 // Global singleton grammar rule table
 // Global singleton grammar rule table
 static grammar_rule rules[TOK_END];
 static grammar_rule rules[TOK_END];
@@ -111,7 +111,7 @@ static grammar_rule rules[TOK_END];
 // MARK: - Prototypes -
 // MARK: - Prototypes -
 static const char *parse_identifier (gravity_parser_t *parser);
 static const char *parse_identifier (gravity_parser_t *parser);
 static gnode_t *parse_statement (gravity_parser_t *parser);
 static gnode_t *parse_statement (gravity_parser_t *parser);
-static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser);
+static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser, bool is_implicit);
 static gnode_t *parse_compound_statement (gravity_parser_t *parser);
 static gnode_t *parse_compound_statement (gravity_parser_t *parser);
 static gnode_t *parse_expression (gravity_parser_t *parser);
 static gnode_t *parse_expression (gravity_parser_t *parser);
 static gnode_t *parse_declaration_statement (gravity_parser_t *parser);
 static gnode_t *parse_declaration_statement (gravity_parser_t *parser);
@@ -294,7 +294,7 @@ gnode_t *parse_function (gravity_parser_t *parser, bool is_declaration, gtoken_t
 	if (!is_implicit) parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
 	if (!is_implicit) parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
 
 
 	// parse optional parameter declaration clause
 	// parse optional parameter declaration clause
-	gnode_r *params = (!is_implicit) ? parse_optional_parameter_declaration(parser) : NULL;
+	gnode_r *params = parse_optional_parameter_declaration(parser, is_implicit);
 
 
 	// check and consume TOK_OP_CLOSED_PARENTHESIS
 	// check and consume TOK_OP_CLOSED_PARENTHESIS
 	if (!is_implicit) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
 	if (!is_implicit) parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
@@ -318,7 +318,7 @@ static char *cstring_from_token (gravity_parser_t *parser, gtoken_s token) {
 	uint32_t len = 0;
 	uint32_t len = 0;
 	const char *buffer = token_string(token, &len);
 	const char *buffer = token_string(token, &len);
 
 
-	char *str = (char *)mem_alloc(len+1);
+	char *str = (char *)mem_alloc(NULL, len+1);
 	memcpy(str, buffer, len);
 	memcpy(str, buffer, len);
 	return str;
 	return str;
 }
 }
@@ -592,7 +592,7 @@ static gnode_t *parse_identifier_expression (gravity_parser_t *parser) {
 	DEBUG_PARSER("parse_identifier_expression");
 	DEBUG_PARSER("parse_identifier_expression");
 	DECLARE_LEXER;
 	DECLARE_LEXER;
 
 
-	const char	*identifier = parse_identifier(parser);
+	const char *identifier = parse_identifier(parser);
 	if (!identifier) return NULL;
 	if (!identifier) return NULL;
 	DEBUG_PARSER("IDENTIFIER: %s", identifier);
 	DEBUG_PARSER("IDENTIFIER: %s", identifier);
 
 
@@ -706,7 +706,7 @@ static gnode_t *parse_analyze_literal_string (gravity_parser_t *parser, gtoken_s
 	gnode_r *r = NULL;
 	gnode_r *r = NULL;
 
 
 	// analyze s (of length len) for escaped characters or for interpolations
 	// analyze s (of length len) for escaped characters or for interpolations
-	char *buffer = mem_alloc(len+1);
+	char *buffer = mem_alloc(NULL, len+1);
 	uint32_t length = 0;
 	uint32_t length = 0;
 
 
 	for (uint32_t i=0; i<len;) {
 	for (uint32_t i=0; i<len;) {
@@ -795,9 +795,9 @@ static gnode_t *parse_analyze_literal_string (gravity_parser_t *parser, gtoken_s
 
 
 					// add expression to r
 					// add expression to r
                     if (subnode) {
                     if (subnode) {
-						if (!r) r = gnode_array_create();
-						if (length) gnode_array_push(r, gnode_literal_string_expr_create(token, buffer, length, true, LAST_DECLARATION()));
-						gnode_array_push(r, subnode);
+                        if (!r) r = gnode_array_create();
+                        if (length) gnode_array_push(r, gnode_literal_string_expr_create(token, buffer, length, true, LAST_DECLARATION()));
+                        gnode_array_push(r, subnode);
                     }
                     }
 
 
 					// free temp lexer
 					// free temp lexer
@@ -805,7 +805,7 @@ static gnode_t *parse_analyze_literal_string (gravity_parser_t *parser, gtoken_s
 					gravity_lexer_free(sublexer);
 					gravity_lexer_free(sublexer);
                     if (!subnode) goto return_string;
                     if (!subnode) goto return_string;
 
 
-					buffer = mem_alloc(len+1);
+					buffer = mem_alloc(NULL, len+1);
 					length = 0;
 					length = 0;
 
 
 					continue;
 					continue;
@@ -1220,7 +1220,7 @@ static gnode_t *parse_getter_setter (gravity_parser_t *parser, gravity_hash_t *m
 			// check if parameters are explicit
 			// check if parameters are explicit
 			if (gravity_lexer_peek(lexer) == TOK_OP_OPEN_PARENTHESIS) {
 			if (gravity_lexer_peek(lexer) == TOK_OP_OPEN_PARENTHESIS) {
 				parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
 				parse_required(parser, TOK_OP_OPEN_PARENTHESIS);
-				params = parse_optional_parameter_declaration(parser);	// add implicit SELF
+				params = parse_optional_parameter_declaration(parser, false);	// add implicit SELF
 				parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
 				parse_required(parser, TOK_OP_CLOSED_PARENTHESIS);
 			} else {
 			} else {
 				params = gnode_array_create();	// add implicit SELF and VALUE params
 				params = gnode_array_create();	// add implicit SELF and VALUE params
@@ -1691,7 +1691,7 @@ static gnode_t *parse_class_declaration (gravity_parser_t *parser, gtoken_t acce
 	}
 	}
 
 
 	// check and consume TOK_OP_OPEN_CURLYBRACE
 	// check and consume TOK_OP_OPEN_CURLYBRACE
-	parse_required(parser, TOK_OP_OPEN_CURLYBRACE);
+	if (storage_specifier != TOK_KEY_EXTERN) parse_required(parser, TOK_OP_OPEN_CURLYBRACE);
 	gnode_r *declarations = gnode_array_create();
 	gnode_r *declarations = gnode_array_create();
 
 
 	// if class is declared inside another class then a hidden implicit privare "outer" instance var at index 0
 	// if class is declared inside another class then a hidden implicit privare "outer" instance var at index 0
@@ -1708,17 +1708,19 @@ static gnode_t *parse_class_declaration (gravity_parser_t *parser, gtoken_t acce
     // create class declaration node
     // create class declaration node
     gnode_class_decl_t *node = (gnode_class_decl_t*) gnode_class_decl_create(token, identifier, access_specifier, storage_specifier, super, protocols, NULL, is_struct, meta, LAST_DECLARATION());
     gnode_class_decl_t *node = (gnode_class_decl_t*) gnode_class_decl_create(token, identifier, access_specifier, storage_specifier, super, protocols, NULL, is_struct, meta, LAST_DECLARATION());
 
 
-	PUSH_DECLARATION(node);
-    peek = gravity_lexer_peek(lexer);
-	while (token_isdeclaration_statement(peek) || token_ismacro(peek)) {
-		gnode_t *decl = parse_declaration_statement(parser);
-        if (decl) gnode_array_push(declarations, decl_check_access_specifier(decl));
+    if (storage_specifier != TOK_KEY_EXTERN) {
+        PUSH_DECLARATION(node);
         peek = gravity_lexer_peek(lexer);
         peek = gravity_lexer_peek(lexer);
-	}
-	POP_DECLARATION();
+        while (token_isdeclaration_statement(peek) || token_ismacro(peek)) {
+            gnode_t *decl = parse_declaration_statement(parser);
+            if (decl) gnode_array_push(declarations, decl_check_access_specifier(decl));
+            peek = gravity_lexer_peek(lexer);
+        }
+        POP_DECLARATION();
+    }
 
 
 	// check and consume TOK_OP_CLOSED_CURLYBRACE
 	// check and consume TOK_OP_CLOSED_CURLYBRACE
-	parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
+	if (storage_specifier != TOK_KEY_EXTERN) parse_required(parser, TOK_OP_CLOSED_CURLYBRACE);
 
 
 	// to check
 	// to check
 	parse_semicolon(parser);
 	parse_semicolon(parser);
@@ -1730,7 +1732,7 @@ static gnode_t *parse_class_declaration (gravity_parser_t *parser, gtoken_t acce
 	return (gnode_t *)node;
 	return (gnode_t *)node;
 }
 }
 
 
-static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser) {
+static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser, bool is_implicit) {
 	DEBUG_PARSER("parse_parameter_declaration");
 	DEBUG_PARSER("parse_parameter_declaration");
 	DECLARE_LEXER;
 	DECLARE_LEXER;
 
 
@@ -1755,6 +1757,7 @@ static gnode_r *parse_optional_parameter_declaration (gravity_parser_t *parser)
 	// memory for the identifier will be deallocated
 	// memory for the identifier will be deallocated
 	node = gnode_variable_create(token, string_dup(SELF_PARAMETER_NAME), type_annotation, 0, NULL, LAST_DECLARATION());
 	node = gnode_variable_create(token, string_dup(SELF_PARAMETER_NAME), type_annotation, 0, NULL, LAST_DECLARATION());
 	if (node) gnode_array_push(params, node);
 	if (node) gnode_array_push(params, node);
+    if (is_implicit) return params;
 
 
 	// parameter declaration clause is ALWAYS optional
 	// parameter declaration clause is ALWAYS optional
 	gtoken_t peek = gravity_lexer_peek(lexer);
 	gtoken_t peek = gravity_lexer_peek(lexer);
@@ -2280,7 +2283,7 @@ static gnode_t *parse_compound_statement (gravity_parser_t *parser) {
         }
         }
 		gnode_t *node = parse_statement(parser);
 		gnode_t *node = parse_statement(parser);
         --parser->depth;
         --parser->depth;
-		if (node) gnode_array_push(stmts, node);
+        if (node) gnode_array_push(stmts, node);
 	}
 	}
 
 
 	// check and consume TOK_OP_CLOSED_CURLYBRACE
 	// check and consume TOK_OP_CLOSED_CURLYBRACE
@@ -2531,7 +2534,7 @@ static uint32_t parser_run (gravity_parser_t *parser) {
 	do {
 	do {
 		while (gravity_lexer_peek(CURRENT_LEXER)) {
 		while (gravity_lexer_peek(CURRENT_LEXER)) {
 			gnode_t *node = parse_statement(parser);
 			gnode_t *node = parse_statement(parser);
-			if (node) gnode_array_push(parser->statements, node);
+            if (node) gnode_array_push(parser->statements, node);
 		}
 		}
 
 
 		// since it is a stack of lexers then check if it is a real EOF
 		// since it is a stack of lexers then check if it is a real EOF
@@ -2578,13 +2581,13 @@ static void parser_appendcode (const char *source, gravity_parser_t *parser) {
 gravity_parser_t *gravity_parser_create (const char *source, size_t len, uint32_t fileid, bool is_static) {
 gravity_parser_t *gravity_parser_create (const char *source, size_t len, uint32_t fileid, bool is_static) {
 	init_grammer_rules();
 	init_grammer_rules();
 
 
-	gravity_parser_t *parser = mem_alloc(sizeof(gravity_parser_t));
+	gravity_parser_t *parser = mem_alloc(NULL, sizeof(gravity_parser_t));
 	if (!parser) return NULL;
 	if (!parser) return NULL;
 
 
 	gravity_lexer_t *lexer = gravity_lexer_create(source, len, fileid, is_static);
 	gravity_lexer_t *lexer = gravity_lexer_create(source, len, fileid, is_static);
 	if (!lexer) goto abort_init;
 	if (!lexer) goto abort_init;
 
 
-	parser->lexer = mem_alloc(sizeof(lexer_r));
+	parser->lexer = mem_alloc(NULL, sizeof(lexer_r));
 	marray_init(*parser->lexer);
 	marray_init(*parser->lexer);
 	marray_push(gravity_lexer_t*, *parser->lexer, lexer);
 	marray_push(gravity_lexer_t*, *parser->lexer, lexer);
 
 

+ 0 - 1
src/compiler/gravity_semacheck2.c

@@ -854,7 +854,6 @@ static void visit_class_decl (gvisitor_t *self, gnode_class_decl_t *node) {
             REPORT_ERROR(id, "Unable to find superclass %s for class %s.", id->value, node->identifier);
             REPORT_ERROR(id, "Unable to find superclass %s for class %s.", id->value, node->identifier);
         } else {
         } else {
             gnode_class_decl_t *target_class = NODE_ISA(target, NODE_CLASS_DECL) ? (gnode_class_decl_t *)target : NULL;
             gnode_class_decl_t *target_class = NODE_ISA(target, NODE_CLASS_DECL) ? (gnode_class_decl_t *)target : NULL;
-
             if (!target_class) {
             if (!target_class) {
                 REPORT_ERROR(id, "Unable to set non class %s as superclass of %s.", id->value, node->identifier);
                 REPORT_ERROR(id, "Unable to set non class %s as superclass of %s.", id->value, node->identifier);
             } else if ((gnode_class_decl_t *)node == (gnode_class_decl_t *)target_class->superclass) {
             } else if ((gnode_class_decl_t *)node == (gnode_class_decl_t *)target_class->superclass) {

+ 2 - 2
src/compiler/gravity_symboltable.c

@@ -63,14 +63,14 @@ static void symboltable_keyvalue_free (gravity_hash_t *hashtable, gravity_value_
 }
 }
 
 
 symboltable_t *symboltable_create (bool is_enum) {
 symboltable_t *symboltable_create (bool is_enum) {
-	symboltable_t	*table = mem_alloc(sizeof(symboltable_t));
+	symboltable_t	*table = mem_alloc(NULL, sizeof(symboltable_t));
 	gravity_hash_t	*hash = gravity_hash_create(0, gravity_value_hash, gravity_value_equals,
 	gravity_hash_t	*hash = gravity_hash_create(0, gravity_value_hash, gravity_value_equals,
 												(is_enum) ? symboltable_keyvalue_free : symboltable_hash_free, NULL);
 												(is_enum) ? symboltable_keyvalue_free : symboltable_hash_free, NULL);
 	if (!table) return NULL;
 	if (!table) return NULL;
 
 
 	// init symbol table
 	// init symbol table
 	table->counter = 0;
 	table->counter = 0;
-	table->stack = mem_alloc(sizeof(ghash_r));
+	table->stack = mem_alloc(NULL, sizeof(ghash_r));
 	scope_stack_init(table->stack);
 	scope_stack_init(table->stack);
 	scope_stack_push(table->stack, hash);
 	scope_stack_push(table->stack, hash);
 
 

+ 67 - 67
src/runtime/gravity_core.c

@@ -159,7 +159,7 @@ static bool convert_object_string (gravity_vm *vm, gravity_value_t *args, uint16
 static inline gravity_value_t convert_map2string (gravity_vm *vm, gravity_map_t *map) {
 static inline gravity_value_t convert_map2string (gravity_vm *vm, gravity_map_t *map) {
     // allocate initial memory to a 512 buffer
     // allocate initial memory to a 512 buffer
     uint32_t len = 512;
     uint32_t len = 512;
-    char *buffer = mem_alloc(len+1);
+    char *buffer = mem_alloc(NULL, len+1);
     buffer[0] = '[';
     buffer[0] = '[';
     uint32_t pos = 1;
     uint32_t pos = 1;
 
 
@@ -198,7 +198,7 @@ static inline gravity_value_t convert_map2string (gravity_vm *vm, gravity_map_t
         // check if buffer needs to be reallocated
         // check if buffer needs to be reallocated
         if (len1 + len2 + pos + 4 > len) {
         if (len1 + len2 + pos + 4 > len) {
             len = (len1 + len2 + pos + 4) + len;
             len = (len1 + len2 + pos + 4) + len;
-            buffer = mem_realloc(buffer, len);
+            buffer = mem_realloc(NULL, buffer, len);
         }
         }
 
 
         // copy key string to new buffer
         // copy key string to new buffer
@@ -232,7 +232,7 @@ static inline gravity_value_t convert_map2string (gravity_vm *vm, gravity_map_t
 static inline gravity_value_t convert_list2string (gravity_vm *vm, gravity_list_t *list) {
 static inline gravity_value_t convert_list2string (gravity_vm *vm, gravity_list_t *list) {
 	// allocate initial memory to a 512 buffer
 	// allocate initial memory to a 512 buffer
 	uint32_t len = 512;
 	uint32_t len = 512;
-	char *buffer = mem_alloc(len+1);
+	char *buffer = mem_alloc(NULL, len+1);
 	buffer[0] = '[';
 	buffer[0] = '[';
 	uint32_t pos = 1;
 	uint32_t pos = 1;
 
 
@@ -244,7 +244,7 @@ static inline gravity_value_t convert_list2string (gravity_vm *vm, gravity_list_
         if (VALUE_ISA_LIST(value) && (VALUE_AS_LIST(value) == list)) {
         if (VALUE_ISA_LIST(value) && (VALUE_AS_LIST(value) == list)) {
             string = NULL;
             string = NULL;
         } else {
         } else {
-			gravity_value_t value2 = convert_value2string(vm, value);
+            gravity_value_t value2 = convert_value2string(vm, value);
             string = VALUE_ISA_VALID(value2) ? VALUE_AS_STRING(value2) : NULL;
             string = VALUE_ISA_VALID(value2) ? VALUE_AS_STRING(value2) : NULL;
         }
         }
 
 
@@ -254,7 +254,7 @@ static inline gravity_value_t convert_list2string (gravity_vm *vm, gravity_list_
 		// check if buffer needs to be reallocated
 		// check if buffer needs to be reallocated
 		if (len1+pos+2 > len) {
 		if (len1+pos+2 > len) {
 			len = (len1+pos+2) + len;
 			len = (len1+pos+2) + len;
-			buffer = mem_realloc(buffer, len);
+			buffer = mem_realloc(NULL, buffer, len);
 		}
 		}
 
 
 		// copy string to new buffer
 		// copy string to new buffer
@@ -526,7 +526,7 @@ static bool object_real_load (gravity_vm *vm, gravity_value_t *args, uint16_t na
         // sanity check
         // sanity check
         uint32_t nivar = c->nivars;
         uint32_t nivar = c->nivars;
         uint32_t nindex = (uint32_t)key.n;
         uint32_t nindex = (uint32_t)key.n;
-        if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index.");
+        if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index in load operation (1).");
 
 
 		if (instance) RETURN_VALUE(instance->ivars[nindex], rindex);	// instance case
 		if (instance) RETURN_VALUE(instance->ivars[nindex], rindex);	// instance case
 		RETURN_VALUE(c->ivars[nindex], rindex);                         // class case
 		RETURN_VALUE(c->ivars[nindex], rindex);                         // class case
@@ -540,12 +540,12 @@ static bool object_real_load (gravity_vm *vm, gravity_value_t *args, uint16_t na
 	// lookup key in class c
 	// lookup key in class c
 	gravity_object_t *obj = (gravity_object_t *)gravity_class_lookup(c, key);
 	gravity_object_t *obj = (gravity_object_t *)gravity_class_lookup(c, key);
     if (!obj) {
     if (!obj) {
-			// not explicitly declared so check for dynamic property in bridge case
-			gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-			if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_getundef)) {
-				if (delegate->bridge_getundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), rindex)) return true;
-			}
-		}
+        // not explicitly declared so check for dynamic property in bridge case
+        gravity_delegate_t *delegate = gravity_vm_delegate(vm);
+        if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_getundef)) {
+            if (delegate->bridge_getundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), rindex)) return true;
+        }
+    }
 	if (!obj) goto execute_notfound;
 	if (!obj) goto execute_notfound;
 
 
 	gravity_closure_t *closure;
 	gravity_closure_t *closure;
@@ -559,9 +559,9 @@ static bool object_real_load (gravity_vm *vm, gravity_value_t *args, uint16_t na
                 // sanity check
                 // sanity check
                 uint32_t nivar = c->nivars;
                 uint32_t nivar = c->nivars;
                 uint32_t nindex = closure->f->index;
                 uint32_t nindex = closure->f->index;
-                if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index.");
+                if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index in load operation (2).");
 
 
-				if (instance) RETURN_VALUE(instance->ivars[closure->f->index], rindex);
+                if (instance) RETURN_VALUE(instance->ivars[closure->f->index], rindex);
 				RETURN_VALUE(c->ivars[closure->f->index], rindex);
 				RETURN_VALUE(c->ivars[closure->f->index], rindex);
 			}
 			}
 
 
@@ -620,7 +620,7 @@ static bool object_store (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
         // sanity check
         // sanity check
         uint32_t nivar = c->nivars;
         uint32_t nivar = c->nivars;
         uint32_t nindex = (uint32_t)key.n;
         uint32_t nindex = (uint32_t)key.n;
-        if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index.");
+        if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index in store operation (1).");
 
 
 		if (instance) instance->ivars[nindex] = value;
 		if (instance) instance->ivars[nindex] = value;
 		else c->ivars[nindex] = value;
 		else c->ivars[nindex] = value;
@@ -635,12 +635,12 @@ static bool object_store (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 	// lookup key in class c
 	// lookup key in class c
 	gravity_object_t *obj = gravity_class_lookup(c, key);
 	gravity_object_t *obj = gravity_class_lookup(c, key);
     if (!obj) {
     if (!obj) {
-			// not explicitly declared so check for dynamic property in bridge case
-			gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-			if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_setundef)) {
-				if (delegate->bridge_setundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), value)) RETURN_NOVALUE();
-			}
-		}
+        // not explicitly declared so check for dynamic property in bridge case
+        gravity_delegate_t *delegate = gravity_vm_delegate(vm);
+        if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_setundef)) {
+            if (delegate->bridge_setundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), value)) RETURN_NOVALUE();
+        }
+    }
 	if (!obj) goto execute_notfound;
 	if (!obj) goto execute_notfound;
 
 
 	gravity_closure_t *closure;
 	gravity_closure_t *closure;
@@ -655,7 +655,7 @@ static bool object_store (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
                 // sanity check
                 // sanity check
                 uint32_t nivar = c->nivars;
                 uint32_t nivar = c->nivars;
                 uint32_t nindex = closure->f->index;
                 uint32_t nindex = closure->f->index;
-                if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index.");
+                if (nindex >= nivar) RETURN_ERROR("Out of bounds ivar index in store operation (2).");
 
 
                 if (instance) instance->ivars[nindex] = value;
                 if (instance) instance->ivars[nindex] = value;
                 else c->ivars[nindex] = value;
                 else c->ivars[nindex] = value;
@@ -793,10 +793,10 @@ static bool list_indexOf (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
             break;
             break;
         }
         }
         ++i;
         ++i;
-	 }
+    }
 
 
-	RETURN_VALUE(result, rindex);
- }
+    RETURN_VALUE(result, rindex);
+}
 
 
 static bool list_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 static bool list_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
 	#pragma unused(vm, nargs)
@@ -842,7 +842,7 @@ static bool list_storeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 
 static bool list_push (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 static bool list_push (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(nargs)
 	#pragma unused(nargs)
-	gravity_list_t	*list = VALUE_AS_LIST(GET_VALUE(0));
+	gravity_list_t *list = VALUE_AS_LIST(GET_VALUE(0));
 	gravity_value_t value = GET_VALUE(1);
 	gravity_value_t value = GET_VALUE(1);
 	marray_push(gravity_value_t, list->array, value);
 	marray_push(gravity_value_t, list->array, value);
 	RETURN_VALUE(VALUE_FROM_INT(marray_size(list->array)), rindex);
 	RETURN_VALUE(VALUE_FROM_INT(marray_size(list->array)), rindex);
@@ -935,12 +935,10 @@ static bool list_join (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, ui
 
 
 	// create a new empty buffer
 	// create a new empty buffer
 	uint32_t alloc = (uint32_t) (marray_size(list->array) * 64);
 	uint32_t alloc = (uint32_t) (marray_size(list->array) * 64);
-    if (alloc > MAX_MEMORY_BLOCK) RETURN_ERROR("Maximum memory block size reached (max %d, requested %d).", MAX_MEMORY_BLOCK, alloc);
-
 	uint32_t len = 0;
 	uint32_t len = 0;
 	uint32_t seplen = (sep) ? VALUE_AS_STRING(GET_VALUE(1))->len : 0;
 	uint32_t seplen = (sep) ? VALUE_AS_STRING(GET_VALUE(1))->len : 0;
-	char *_buffer = mem_alloc(alloc);
-	if (!_buffer) RETURN_ERROR("Not enought memory to allocate a buffer for the join operation.");
+	char *_buffer = mem_alloc(vm, alloc);
+    CHECK_MEM_ALLOC(_buffer);
 
 
 	register gravity_int_t n = marray_size(list->array);
 	register gravity_int_t n = marray_size(list->array);
 	register gravity_int_t i = 0;
 	register gravity_int_t i = 0;
@@ -961,17 +959,10 @@ static bool list_join (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, ui
 		// check if buffer needs to be reallocated
 		// check if buffer needs to be reallocated
 		if (free_mem < req + seplen) {
 		if (free_mem < req + seplen) {
             uint64_t to_alloc = alloc + (req + seplen) * 2 + 4096;
             uint64_t to_alloc = alloc + (req + seplen) * 2 + 4096;
-
-            // sanity check
-            if (to_alloc > MAX_MEMORY_BLOCK) {
-                mem_free(_buffer);
-                RETURN_ERROR("Maximum memory block size reached (max %d, requested %llu).", MAX_MEMORY_BLOCK, to_alloc);
-            }
-
-			_buffer = mem_realloc(_buffer, (uint32_t)to_alloc);
+			_buffer = mem_realloc(vm, _buffer, (uint32_t)to_alloc);
             if (!_buffer) {
             if (!_buffer) {
                 mem_free(_buffer);
                 mem_free(_buffer);
-                RETURN_ERROR("Not enought memory to re-allocate a buffer for the join operation.");
+                RETURN_ERROR_SIMPLE();
             }
             }
 			alloc = (uint32_t)to_alloc;
 			alloc = (uint32_t)to_alloc;
 		}
 		}
@@ -1675,8 +1666,11 @@ static bool operator_string_add (gravity_vm *vm, gravity_value_t *args, uint16_t
 	char *s = NULL;
 	char *s = NULL;
 
 
 	// check if I can save an allocation
 	// check if I can save an allocation
-	if (len+1<sizeof(buffer)) s = buffer;
-	else s = mem_alloc(len+1);
+	if (len+1 < sizeof(buffer)) s = buffer;
+    else {
+        s = mem_alloc(vm, len+1);
+        CHECK_MEM_ALLOC(s);
+    }
 
 
 	memcpy(s, s1->s, s1->len);
 	memcpy(s, s1->s, s1->len);
 	memcpy(s+s1->len, s2->s, s2->len);
 	memcpy(s+s1->len, s2->s, s2->len);
@@ -1709,7 +1703,8 @@ static bool operator_string_sub (gravity_vm *vm, gravity_value_t *args, uint16_t
 
 
 	// substring found but cannot be entirely considered
 	// substring found but cannot be entirely considered
 	uint32_t alloc = MAXNUM(s1->len + s2->len +1, DEFAULT_MINSTRING_SIZE);
 	uint32_t alloc = MAXNUM(s1->len + s2->len +1, DEFAULT_MINSTRING_SIZE);
-	char *s = mem_alloc(alloc);
+	char *s = mem_alloc(vm, alloc);
+    CHECK_MEM_ALLOC(s);
 
 
 	uint32_t seek = (uint32_t)(found - s1->s);
 	uint32_t seek = (uint32_t)(found - s1->s);
 	uint32_t len = seek + (flen - s2->len);
 	uint32_t len = seek + (flen - s2->len);
@@ -1849,8 +1844,8 @@ static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 
 
 	// figure out the size of the array we need to make to hold the new string
 	// figure out the size of the array we need to make to hold the new string
 	uint32_t new_size = (uint32_t)(main_str->len * times_to_repeat);
 	uint32_t new_size = (uint32_t)(main_str->len * times_to_repeat);
-	char *new_str = mem_alloc(new_size+1);
-	if (!new_str) RETURN_ERROR("Unable to allocate a String so big (%d)", new_size);
+	char *new_str = mem_alloc(vm, new_size+1);
+    CHECK_MEM_ALLOC(new_str);
 
 
     uint32_t seek = 0;
     uint32_t seek = 0;
 	for (uint32_t i = 0; i < times_to_repeat; ++i) {
 	for (uint32_t i = 0; i < times_to_repeat; ++i) {
@@ -1865,8 +1860,8 @@ static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
 
-	char *ret = mem_alloc(main_str->len + 1);
-	if (!ret) RETURN_ERROR("Unable to allocate a String so big (%d)", main_str->len);
+	char *ret = mem_alloc(vm, main_str->len + 1);
+	CHECK_MEM_ALLOC(ret);
 	strcpy(ret, main_str->s);
 	strcpy(ret, main_str->s);
 
 
 	// if no arguments passed, change the whole string to uppercase
 	// if no arguments passed, change the whole string to uppercase
@@ -1904,8 +1899,8 @@ static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
 
-	char *ret = mem_alloc(main_str->len + 1);
-	if (!ret) RETURN_ERROR("Unable to allocate a String so big (%d)", main_str->len);
+	char *ret = mem_alloc(vm, main_str->len + 1);
+    CHECK_MEM_ALLOC(ret);
 	strcpy(ret, main_str->s);
 	strcpy(ret, main_str->s);
 
 
 	// if no arguments passed, change the whole string to lowercase
 	// if no arguments passed, change the whole string to lowercase
@@ -1971,8 +1966,9 @@ static bool string_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 
 
 	bool is_forward = first_index <= second_index;
 	bool is_forward = first_index <= second_index;
 	if (!is_forward) {
 	if (!is_forward) {
-		char *original = mem_alloc(string->len);
-		if (!original) RETURN_ERROR("Unable to allocate a String so big (%d)", string->len);
+		char *original = mem_alloc(vm, string->len);
+        CHECK_MEM_ALLOC(original);
+
 		// without copying it, we would be modifying the original string
 		// without copying it, we would be modifying the original string
 		strncpy((char *)original, string->s, string->len);
 		strncpy((char *)original, string->s, string->len);
 		uint32_t original_len = (uint32_t) string->len;
 		uint32_t original_len = (uint32_t) string->len;
@@ -2170,13 +2166,13 @@ static bool fiber_yield (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 
     // in no caller then this is just a NOP
     // in no caller then this is just a NOP
     if (fiber->caller) {
     if (fiber->caller) {
-		gravity_vm_setfiber(vm, fiber->caller);
+        gravity_vm_setfiber(vm, fiber->caller);
 
 
-		// unhook this fiber from the one that called it
-		fiber->caller = NULL;
-		fiber->trying = false;
+        // unhook this fiber from the one that called it
+        fiber->caller = NULL;
+        fiber->trying = false;
 
 
-		RETURN_FIBER();
+        RETURN_FIBER();
     } else {
     } else {
         RETURN_NOVALUE();
         RETURN_NOVALUE();
     }
     }
@@ -2643,10 +2639,12 @@ static void gravity_core_init (void) {
 
 
     closure = computed_property_create(NULL, NEW_FUNCTION(system_get), NEW_FUNCTION(system_set));
     closure = computed_property_create(NULL, NEW_FUNCTION(system_get), NEW_FUNCTION(system_set));
 	gravity_value_t value = VALUE_FROM_OBJECT(closure);
 	gravity_value_t value = VALUE_FROM_OBJECT(closure);
-	gravity_class_bind(system_meta, "gcenabled", value);
-	gravity_class_bind(system_meta, "gcminthreshold", value);
-	gravity_class_bind(system_meta, "gcthreshold", value);
-	gravity_class_bind(system_meta, "gcratio", value);
+	gravity_class_bind(system_meta, GRAVITY_VM_GCENABLED_KEY, value);
+	gravity_class_bind(system_meta, GRAVITY_VM_GCMINTHRESHOLD_KEY, value);
+	gravity_class_bind(system_meta, GRAVITY_VM_GCTHRESHOLD_KEY, value);
+	gravity_class_bind(system_meta, GRAVITY_VM_GCRATIO_KEY, value);
+    gravity_class_bind(system_meta, GRAVITY_VM_MAXCALLS_KEY, value);
+    gravity_class_bind(system_meta, GRAVITY_VM_MAXBLOCK_KEY, value);
 
 
 	// INIT META
 	// INIT META
 	SETMETA_INITED(gravity_class_int);
 	SETMETA_INITED(gravity_class_int);
@@ -2693,7 +2691,7 @@ void gravity_core_free (void) {
     computed_property_free(gravity_class_float, "radians", true);
     computed_property_free(gravity_class_float, "radians", true);
     computed_property_free(gravity_class_float, "degrees", true);
     computed_property_free(gravity_class_float, "degrees", true);
     gravity_class_t *system_meta = gravity_class_get_meta(gravity_class_system);
     gravity_class_t *system_meta = gravity_class_get_meta(gravity_class_system);
-    computed_property_free(system_meta, "gcenabled", true);
+    computed_property_free(system_meta, GRAVITY_VM_GCENABLED_KEY, true);
 
 
 	gravity_class_free_core(NULL, gravity_class_get_meta(gravity_class_int));
 	gravity_class_free_core(NULL, gravity_class_get_meta(gravity_class_int));
 	gravity_class_free_core(NULL, gravity_class_int);
 	gravity_class_free_core(NULL, gravity_class_int);
@@ -2723,9 +2721,11 @@ void gravity_core_free (void) {
 	gravity_class_free_core(NULL, gravity_class_upvalue);
 	gravity_class_free_core(NULL, gravity_class_upvalue);
 
 
 	// before freeing the meta class we need to remove entries with duplicated functions
 	// before freeing the meta class we need to remove entries with duplicated functions
-	{STATICVALUE_FROM_STRING(key, "gcminthreshold", strlen("gcminthreshold")); gravity_hash_remove(system_meta->htable, key);}
-	{STATICVALUE_FROM_STRING(key, "gcthreshold", strlen("gcthreshold")); gravity_hash_remove(system_meta->htable, key);}
-	{STATICVALUE_FROM_STRING(key, "gcratio", strlen("gcratio")); gravity_hash_remove(system_meta->htable, key);}
+	{STATICVALUE_FROM_STRING(key, GRAVITY_VM_GCMINTHRESHOLD_KEY, strlen(GRAVITY_VM_GCMINTHRESHOLD_KEY)); gravity_hash_remove(system_meta->htable, key);}
+	{STATICVALUE_FROM_STRING(key, GRAVITY_VM_GCTHRESHOLD_KEY, strlen(GRAVITY_VM_GCTHRESHOLD_KEY)); gravity_hash_remove(system_meta->htable, key);}
+	{STATICVALUE_FROM_STRING(key, GRAVITY_VM_GCRATIO_KEY, strlen(GRAVITY_VM_GCRATIO_KEY)); gravity_hash_remove(system_meta->htable, key);}
+    {STATICVALUE_FROM_STRING(key, GRAVITY_VM_MAXCALLS_KEY, strlen(GRAVITY_VM_MAXCALLS_KEY)); gravity_hash_remove(system_meta->htable, key);}
+    {STATICVALUE_FROM_STRING(key, GRAVITY_VM_MAXBLOCK_KEY, strlen(GRAVITY_VM_MAXBLOCK_KEY)); gravity_hash_remove(system_meta->htable, key);}
 	gravity_class_free_core(NULL, system_meta);
 	gravity_class_free_core(NULL, system_meta);
 	gravity_class_free_core(NULL, gravity_class_system);
 	gravity_class_free_core(NULL, gravity_class_system);
 
 
@@ -2814,10 +2814,10 @@ gravity_class_t *gravity_core_class_from_name (const char *name) {
 bool gravity_iscore_class (gravity_class_t *c) {
 bool gravity_iscore_class (gravity_class_t *c) {
 	// first check if it is a class
 	// first check if it is a class
 	if ((c == gravity_class_object) || (c == gravity_class_class) || (c == gravity_class_bool) ||
 	if ((c == gravity_class_object) || (c == gravity_class_class) || (c == gravity_class_bool) ||
-			(c == gravity_class_null) || (c == gravity_class_int) || (c == gravity_class_float) ||
-			(c == gravity_class_function) || (c == gravity_class_fiber) || (c == gravity_class_string) ||
-			(c == gravity_class_instance) || (c == gravity_class_list) || (c == gravity_class_map) ||
-			(c == gravity_class_range) || (c == gravity_class_system) || (c == gravity_class_closure) ||
+		(c == gravity_class_null) || (c == gravity_class_int) || (c == gravity_class_float) ||
+		(c == gravity_class_function) || (c == gravity_class_fiber) || (c == gravity_class_string) ||
+		(c == gravity_class_instance) || (c == gravity_class_list) || (c == gravity_class_map) ||
+		(c == gravity_class_range) || (c == gravity_class_system) || (c == gravity_class_closure) ||
 		(c == gravity_class_upvalue)) return true;
 		(c == gravity_class_upvalue)) return true;
 
 
 	// if class check is false then check for meta
 	// if class check is false then check for meta

+ 34 - 26
src/runtime/gravity_vm.c

@@ -37,7 +37,7 @@ struct gravity_vm {
 	uint32_t			pc;									// program counter
 	uint32_t			pc;									// program counter
 	double				time;								// useful timer for the main function
 	double				time;								// useful timer for the main function
 	bool				aborted;							// set when VM has generated a runtime error
 	bool				aborted;							// set when VM has generated a runtime error
-    uint32_t            maxncalls;                          // maximum number of nested c calls
+    uint32_t            maxccalls;                          // maximum number of nested c calls
     uint32_t            nccalls;                            // current number of nested c calls
     uint32_t            nccalls;                            // current number of nested c calls
 
 
 	// anonymous names
 	// anonymous names
@@ -52,6 +52,7 @@ struct gravity_vm {
 	// garbage collector
 	// garbage collector
 	bool				gcenabled;							// flag to enable/disable garbage collector
 	bool				gcenabled;							// flag to enable/disable garbage collector
 	gravity_int_t		memallocated;						// total number of allocated memory
 	gravity_int_t		memallocated;						// total number of allocated memory
+    gravity_int_t       maxmemblock;                        // maximum block memory size allowed to allocate
 	gravity_object_t	*gchead;							// head of garbage collected objects
 	gravity_object_t	*gchead;							// head of garbage collected objects
 	gravity_int_t		gcminthreshold;						// minimum GC threshold size to avoid spending too much time in GC
 	gravity_int_t		gcminthreshold;						// minimum GC threshold size to avoid spending too much time in GC
 	gravity_int_t		gcthreshold;						// memory required to trigger a GC
 	gravity_int_t		gcthreshold;						// memory required to trigger a GC
@@ -170,7 +171,7 @@ static inline gravity_callframe_t *gravity_new_callframe (gravity_vm *vm, gravit
 	// check if there are enought slots in the call frame and optionally create new cframes
 	// check if there are enought slots in the call frame and optionally create new cframes
 	if (fiber->framesalloc - fiber->nframes < 1) {
 	if (fiber->framesalloc - fiber->nframes < 1) {
 		uint32_t new_size = fiber->framesalloc * 2;
 		uint32_t new_size = fiber->framesalloc * 2;
-        void *ptr = mem_realloc(fiber->frames, sizeof(gravity_callframe_t) * new_size);
+        void *ptr = mem_realloc(NULL, fiber->frames, sizeof(gravity_callframe_t) * new_size);
         if (!ptr) {
         if (!ptr) {
             // frames reallocation failed means that there is a very high probability to be into an infinite loop
             // frames reallocation failed means that there is a very high probability to be into an infinite loop
             report_runtime_error(vm, GRAVITY_ERROR_RUNTIME, "Infinite loop detected. Current execution must be aborted.");
             report_runtime_error(vm, GRAVITY_ERROR_RUNTIME, "Infinite loop detected. Current execution must be aborted.");
@@ -203,7 +204,7 @@ static inline bool gravity_check_stack (gravity_vm *vm, gravity_fiber_t *fiber,
 	// perform stack reallocation (power_of2_ceil returns 0 if argument is bigger than 2^31)
 	// perform stack reallocation (power_of2_ceil returns 0 if argument is bigger than 2^31)
 	uint32_t new_size = power_of2_ceil(fiber->stackalloc + stack_needed);
 	uint32_t new_size = power_of2_ceil(fiber->stackalloc + stack_needed);
     bool size_condition = (new_size && (uint64_t)new_size >= (uint64_t)(fiber->stackalloc + stack_needed) && ((sizeof(gravity_value_t) * new_size) < SIZE_MAX));
     bool size_condition = (new_size && (uint64_t)new_size >= (uint64_t)(fiber->stackalloc + stack_needed) && ((sizeof(gravity_value_t) * new_size) < SIZE_MAX));
-    void *ptr = (size_condition) ? mem_realloc(fiber->stack, sizeof(gravity_value_t) * new_size) : NULL;
+    void *ptr = (size_condition) ? mem_realloc(NULL, fiber->stack, sizeof(gravity_value_t) * new_size) : NULL;
     if (!ptr) {
     if (!ptr) {
         // restore stacktop to previous state
         // restore stacktop to previous state
         fiber->stacktop -= rneeds;
         fiber->stacktop -= rneeds;
@@ -1304,8 +1305,8 @@ static bool gravity_vm_exec (gravity_vm *vm) {
 	return true;
 	return true;
 }
 }
 
 
-gravity_vm *gravity_vm_new (gravity_delegate_t *delegate/*, uint32_t context_size, gravity_int_t gcminthreshold, gravity_int_t gcthreshold, gravity_float_t gcratio*/) {
-	gravity_vm *vm = mem_alloc(sizeof(gravity_vm));
+gravity_vm *gravity_vm_new (gravity_delegate_t *delegate) {
+	gravity_vm *vm = mem_alloc(NULL, sizeof(gravity_vm));
 	if (!vm) return NULL;
 	if (!vm) return NULL;
 
 
 	// setup default callbacks
 	// setup default callbacks
@@ -1314,18 +1315,19 @@ gravity_vm *gravity_vm_new (gravity_delegate_t *delegate/*, uint32_t context_siz
 
 
 	// allocate default fiber
 	// allocate default fiber
 	vm->fiber = gravity_fiber_new(vm, NULL, 0, 0);
 	vm->fiber = gravity_fiber_new(vm, NULL, 0, 0);
-    vm->maxncalls = MAX_CCALLS;
+    vm->maxccalls = MAX_CCALLS;
 
 
 	vm->pc = 0;
 	vm->pc = 0;
 	vm->delegate = delegate;
 	vm->delegate = delegate;
-	vm->context = gravity_hash_create(/*(context_size) ? context_size : */DEFAULT_CONTEXT_SIZE, gravity_value_hash, gravity_value_equals, NULL, NULL);
+	vm->context = gravity_hash_create(DEFAULT_CONTEXT_SIZE, gravity_value_hash, gravity_value_equals, NULL, NULL);
 
 
 	// garbage collector
 	// garbage collector
 	vm->gcenabled = true;
 	vm->gcenabled = true;
-	vm->gcminthreshold = /*(gcminthreshold) ? gcminthreshold :*/ DEFAULT_CG_MINTHRESHOLD;
-	vm->gcthreshold = /*(gcthreshold) ? gcthreshold :*/ DEFAULT_CG_THRESHOLD;
-	vm->gcratio = /*(gcratio) ? gcratio :*/ DEFAULT_CG_RATIO;
+	vm->gcminthreshold = DEFAULT_CG_MINTHRESHOLD;
+	vm->gcthreshold = DEFAULT_CG_THRESHOLD;
+	vm->gcratio = DEFAULT_CG_RATIO;
 	vm->memallocated = 0;
 	vm->memallocated = 0;
+    vm->maxmemblock = MAX_MEMORY_BLOCK;
 	marray_init(vm->graylist);
 	marray_init(vm->graylist);
 	marray_init(vm->gcsave);
 	marray_init(vm->gcsave);
 
 
@@ -1338,7 +1340,7 @@ gravity_vm *gravity_vm_new (gravity_delegate_t *delegate/*, uint32_t context_siz
 }
 }
 
 
 gravity_vm *gravity_vm_newmini (void) {
 gravity_vm *gravity_vm_newmini (void) {
-	gravity_vm *vm = mem_alloc(sizeof(gravity_vm));
+	gravity_vm *vm = mem_alloc(NULL, sizeof(gravity_vm));
 	return vm;
 	return vm;
 }
 }
 
 
@@ -1399,7 +1401,7 @@ void gravity_vm_seterror (gravity_vm* vm, const char *format, ...) {
 
 
 	if (fiber->error) mem_free(fiber->error);
 	if (fiber->error) mem_free(fiber->error);
 	size_t err_size = 2048;
 	size_t err_size = 2048;
-	fiber->error = mem_alloc(err_size);
+	fiber->error = mem_alloc(NULL, err_size);
 
 
 	va_list arg;
 	va_list arg;
 	va_start (arg, format);
 	va_start (arg, format);
@@ -1523,7 +1525,7 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
 	switch (f->tag) {
 	switch (f->tag) {
 		case EXEC_TYPE_NATIVE:
 		case EXEC_TYPE_NATIVE:
             ++vm->nccalls;
             ++vm->nccalls;
-            if (vm->nccalls > vm->maxncalls) RUNTIME_ERROR("Maximum number of nested C calls reached (%d).", vm->maxncalls);
+            if (vm->nccalls > vm->maxccalls) RUNTIME_ERROR("Maximum number of nested C calls reached (%d).", vm->maxccalls);
 			result = gravity_vm_exec(vm);
 			result = gravity_vm_exec(vm);
             --vm->nccalls;
             --vm->nccalls;
 			break;
 			break;
@@ -1646,26 +1648,32 @@ void gravity_vm_memupdate (gravity_vm *vm, gravity_int_t value) {
 	vm->memallocated += value;
 	vm->memallocated += value;
 }
 }
 
 
+gravity_int_t gravity_vm_maxmemblock (gravity_vm *vm) {
+    return vm->maxmemblock;
+}
+
 // MARK: - Get/Set Internal Settings -
 // MARK: - Get/Set Internal Settings -
 
 
 gravity_value_t gravity_vm_get (gravity_vm *vm, const char *key) {
 gravity_value_t gravity_vm_get (gravity_vm *vm, const char *key) {
 	if (key) {
 	if (key) {
-		if (strcmp(key, "gcenabled") == 0) return VALUE_FROM_BOOL(vm->gcenabled);
-		if (strcmp(key, "gcminthreshold") == 0) return VALUE_FROM_INT(vm->gcminthreshold);
-		if (strcmp(key, "gcthreshold") == 0) return VALUE_FROM_INT(vm->gcthreshold);
-		if (strcmp(key, "gcratio") == 0) return VALUE_FROM_FLOAT(vm->gcratio);
-        if (strcmp(key, "maxncalls") == 0) return VALUE_FROM_INT(vm->maxncalls);
+		if (strcmp(key, GRAVITY_VM_GCENABLED_KEY) == 0) return VALUE_FROM_BOOL(vm->gcenabled);
+		if (strcmp(key, GRAVITY_VM_GCMINTHRESHOLD_KEY) == 0) return VALUE_FROM_INT(vm->gcminthreshold);
+		if (strcmp(key, GRAVITY_VM_GCTHRESHOLD_KEY) == 0) return VALUE_FROM_INT(vm->gcthreshold);
+		if (strcmp(key, GRAVITY_VM_GCRATIO_KEY) == 0) return VALUE_FROM_FLOAT(vm->gcratio);
+        if (strcmp(key, GRAVITY_VM_MAXCALLS_KEY) == 0) return VALUE_FROM_INT(vm->maxccalls);
+        if (strcmp(key, GRAVITY_VM_MAXBLOCK_KEY) == 0) return VALUE_FROM_INT(vm->maxmemblock);
 	}
 	}
 	return VALUE_FROM_NULL;
 	return VALUE_FROM_NULL;
 }
 }
 
 
 bool gravity_vm_set (gravity_vm *vm, const char *key, gravity_value_t value) {
 bool gravity_vm_set (gravity_vm *vm, const char *key, gravity_value_t value) {
 	if (key) {
 	if (key) {
-		if ((strcmp(key, "gcenabled") == 0) && VALUE_ISA_BOOL(value)) {vm->gcenabled = VALUE_AS_BOOL(value); return true;}
-		if ((strcmp(key, "gcminthreshold") == 0) && VALUE_ISA_INT(value)) {vm->gcminthreshold = VALUE_AS_INT(value); return true;}
-		if ((strcmp(key, "gcthreshold") == 0) && VALUE_ISA_INT(value)) {vm->gcthreshold = VALUE_AS_INT(value); return true;}
-		if ((strcmp(key, "gcratio") == 0) && VALUE_ISA_FLOAT(value)) {vm->gcratio = VALUE_AS_FLOAT(value); return true;}
-        if ((strcmp(key, "maxncalls") == 0) && VALUE_ISA_INT(value)) {vm->maxncalls = (uint32_t)VALUE_AS_INT(value); return true;}
+		if ((strcmp(key, GRAVITY_VM_GCENABLED_KEY) == 0) && VALUE_ISA_BOOL(value)) {vm->gcenabled = VALUE_AS_BOOL(value); return true;}
+		if ((strcmp(key, GRAVITY_VM_GCMINTHRESHOLD_KEY) == 0) && VALUE_ISA_INT(value)) {vm->gcminthreshold = VALUE_AS_INT(value); return true;}
+		if ((strcmp(key, GRAVITY_VM_GCTHRESHOLD_KEY) == 0) && VALUE_ISA_INT(value)) {vm->gcthreshold = VALUE_AS_INT(value); return true;}
+		if ((strcmp(key, GRAVITY_VM_GCRATIO_KEY) == 0) && VALUE_ISA_FLOAT(value)) {vm->gcratio = VALUE_AS_FLOAT(value); return true;}
+        if ((strcmp(key, GRAVITY_VM_MAXCALLS_KEY) == 0) && VALUE_ISA_INT(value)) {vm->maxccalls = (uint32_t)VALUE_AS_INT(value); return true;}
+        if ((strcmp(key, GRAVITY_VM_MAXBLOCK_KEY) == 0) && VALUE_ISA_INT(value)) {vm->maxmemblock = (uint32_t)VALUE_AS_INT(value); return true;}
 	}
 	}
 	return false;
 	return false;
 }
 }
@@ -1794,9 +1802,9 @@ gravity_closure_t *gravity_vm_loadfile (gravity_vm *vm, const char *path) {
 }
 }
 
 
 gravity_closure_t *gravity_vm_loadbuffer (gravity_vm *vm, const char *buffer, size_t len) {
 gravity_closure_t *gravity_vm_loadbuffer (gravity_vm *vm, const char *buffer, size_t len) {
-	// state buffer for further processing super classes
-	void_r objects;
-	marray_init(objects);
+    // state buffer for further processing super classes
+    void_r objects;
+    marray_init(objects);
 
 
     // start json parsing
     // start json parsing
 	json_value *json = json_parse (buffer, len);
 	json_value *json = json_parse (buffer, len);

+ 8 - 1
src/runtime/gravity_vm.h

@@ -16,6 +16,13 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+#define GRAVITY_VM_GCENABLED_KEY            "gcenabled"
+#define GRAVITY_VM_GCMINTHRESHOLD_KEY       "gcminthreshold"
+#define GRAVITY_VM_GCTHRESHOLD_KEY          "gcthreshold"
+#define GRAVITY_VM_GCRATIO_KEY              "gcratio"
+#define GRAVITY_VM_MAXCALLS_KEY             "maxcalls"
+#define GRAVITY_VM_MAXBLOCK_KEY             "maxblock"
+
 typedef bool (*vm_filter_cb) (gravity_object_t *obj);
 typedef bool (*vm_filter_cb) (gravity_object_t *obj);
 typedef void (*vm_transfer_cb) (gravity_vm *vm, gravity_object_t *obj);
 typedef void (*vm_transfer_cb) (gravity_vm *vm, gravity_object_t *obj);
 typedef void (*vm_cleanup_cb) (gravity_vm *vm);
 typedef void (*vm_cleanup_cb) (gravity_vm *vm);
@@ -44,7 +51,6 @@ GRAVITY_API bool				gravity_vm_isaborted (gravity_vm *vm);
 GRAVITY_API void				gravity_vm_setaborted (gravity_vm *vm);
 GRAVITY_API void				gravity_vm_setaborted (gravity_vm *vm);
 GRAVITY_API gravity_closure_t   *gravity_vm_getclosure (gravity_vm *vm);
 GRAVITY_API gravity_closure_t   *gravity_vm_getclosure (gravity_vm *vm);
 
 
-
 GRAVITY_API void				gravity_gray_value (gravity_vm* vm, gravity_value_t v);
 GRAVITY_API void				gravity_gray_value (gravity_vm* vm, gravity_value_t v);
 GRAVITY_API void				gravity_gray_object (gravity_vm* vm, gravity_object_t *obj);
 GRAVITY_API void				gravity_gray_object (gravity_vm* vm, gravity_object_t *obj);
 GRAVITY_API void				gravity_gc_start (gravity_vm* vm);
 GRAVITY_API void				gravity_gc_start (gravity_vm* vm);
@@ -66,6 +72,7 @@ GRAVITY_API gravity_value_t		gravity_vm_getslot (gravity_vm *vm, uint32_t index)
 GRAVITY_API void				gravity_vm_setdata (gravity_vm *vm, void *data);
 GRAVITY_API void				gravity_vm_setdata (gravity_vm *vm, void *data);
 GRAVITY_API void				*gravity_vm_getdata (gravity_vm *vm);
 GRAVITY_API void				*gravity_vm_getdata (gravity_vm *vm);
 GRAVITY_API void				gravity_vm_memupdate (gravity_vm *vm, gravity_int_t value);
 GRAVITY_API void				gravity_vm_memupdate (gravity_vm *vm, gravity_int_t value);
+GRAVITY_API gravity_int_t       gravity_vm_maxmemblock (gravity_vm *vm);
 
 
 GRAVITY_API gravity_value_t		gravity_vm_get (gravity_vm *vm, const char *key);
 GRAVITY_API gravity_value_t		gravity_vm_get (gravity_vm *vm, const char *key);
 GRAVITY_API bool				gravity_vm_set (gravity_vm *vm, const char *key, gravity_value_t value);
 GRAVITY_API bool				gravity_vm_set (gravity_vm *vm, const char *key, gravity_value_t value);

+ 5 - 1
src/runtime/gravity_vmmacros.h

@@ -280,7 +280,11 @@
                                                         gravity_vm_setslot(vm, VALUE_FROM_NULL, rindex);                                    \
                                                         gravity_vm_setslot(vm, VALUE_FROM_NULL, rindex);                                    \
                                                         return false;                                                                       \
                                                         return false;                                                                       \
                                                     } while(0)
                                                     } while(0)
-
+#define RETURN_ERROR_SIMPLE()                       do {                                                                                    \
+                                                        gravity_vm_setslot(vm, VALUE_FROM_NULL, rindex);                                    \
+                                                        return false;                                                                       \
+                                                    } while(0)
+#define CHECK_MEM_ALLOC(_ptr)                       if (!_ptr) RETURN_ERROR_SIMPLE();
 #define DECLARE_1VARIABLE(_v,_idx)                  register gravity_value_t _v = GET_VALUE(_idx)
 #define DECLARE_1VARIABLE(_v,_idx)                  register gravity_value_t _v = GET_VALUE(_idx)
 #define DECLARE_2VARIABLES(_v1,_v2,_idx1,_idx2)     DECLARE_1VARIABLE(_v1,_idx1);DECLARE_1VARIABLE(_v2,_idx2)
 #define DECLARE_2VARIABLES(_v1,_v2,_idx1,_idx2)     DECLARE_1VARIABLE(_v1,_idx1);DECLARE_1VARIABLE(_v2,_idx2)
 
 

+ 4 - 4
src/shared/gravity_hash.c

@@ -162,9 +162,9 @@ gravity_hash_t *gravity_hash_create (uint32_t size, gravity_hash_compute_fn comp
 	if ((!compute) || (!isequal)) return NULL;
 	if ((!compute) || (!isequal)) return NULL;
 	if (size == 0) size = GRAVITYHASH_DEFAULT_SIZE;
 	if (size == 0) size = GRAVITYHASH_DEFAULT_SIZE;
 
 
-	gravity_hash_t *hashtable = (gravity_hash_t *)mem_alloc(sizeof(gravity_hash_t));
+	gravity_hash_t *hashtable = (gravity_hash_t *)mem_alloc(NULL, sizeof(gravity_hash_t));
 	if (!hashtable) return NULL;
 	if (!hashtable) return NULL;
-	if (!(hashtable->nodes = mem_calloc(size, sizeof(hash_node_t*)))) {mem_free(hashtable); return NULL;}
+	if (!(hashtable->nodes = mem_calloc(NULL, size, sizeof(hash_node_t*)))) {mem_free(hashtable); return NULL;}
 
 
 	hashtable->compute_fn = compute;
 	hashtable->compute_fn = compute;
 	hashtable->isequal_fn = isequal;
 	hashtable->isequal_fn = isequal;
@@ -211,7 +211,7 @@ static inline int gravity_hash_resize (gravity_hash_t *hashtable) {
 		.isequal_fn = hashtable->isequal_fn,
 		.isequal_fn = hashtable->isequal_fn,
 		.compute_fn = hashtable->compute_fn
 		.compute_fn = hashtable->compute_fn
 	};
 	};
-	if (!(newtbl.nodes = mem_calloc(size, sizeof(hash_node_t*)))) return -1;
+	if (!(newtbl.nodes = mem_calloc(NULL, size, sizeof(hash_node_t*)))) return -1;
 
 
 	hash_node_t *node, *next;
 	hash_node_t *node, *next;
 	for (uint32_t n = 0; n < hashtable->size; ++n) {
 	for (uint32_t n = 0; n < hashtable->size; ++n) {
@@ -285,7 +285,7 @@ bool gravity_hash_insert (gravity_hash_t *hashtable, gravity_value_t key, gravit
 	}
 	}
 
 
 	// allocate new entry and set new data
 	// allocate new entry and set new data
-	if (!(node = mem_alloc(sizeof(hash_node_t)))) return -1;
+	if (!(node = mem_alloc(NULL, sizeof(hash_node_t)))) return -1;
 	node->key = key;
 	node->key = key;
 	node->hash = hash;
 	node->hash = hash;
 	node->value = value;
 	node->value = value;

+ 30 - 10
src/shared/gravity_memory.c

@@ -7,11 +7,27 @@
 //
 //
 
 
 #include "gravity_memory.h"
 #include "gravity_memory.h"
-#if GRAVITY_MEMORY_DEBUG
+#include "gravity_vm.h"
 
 
-#include <stdlib.h>
-#include <strings.h>
+#if !GRAVITY_MEMORY_DEBUG
 
 
+void *gravity_calloc(gravity_vm *vm, size_t count, size_t size) {
+    if (vm && ((count * size) >= gravity_vm_maxmemblock(vm))) {
+        gravity_vm_seterror(vm, "Maximum memory allocation block size reached (req: %d, max: %lld).", (count * size), (int64_t)gravity_vm_maxmemblock(vm));
+        return NULL;
+    }
+    return calloc(count, size);;
+}
+
+void *gravity_realloc(gravity_vm *vm, void *ptr, size_t new_size) {
+    if (vm && (new_size >= gravity_vm_maxmemblock(vm))) {
+        gravity_vm_seterror(vm, "Maximum memory re-allocation block size reached (req: %d, max: %lld).", new_size, (int64_t)gravity_vm_maxmemblock(vm));
+        return NULL;
+    }
+    return realloc(ptr, new_size);
+}
+
+#else
 #if _WIN32
 #if _WIN32
 #include <imagehlp.h>
 #include <imagehlp.h>
 #else
 #else
@@ -93,7 +109,8 @@ void memdebug_init (void) {
 	memdebug.aslot = SLOT_MIN;
 	memdebug.aslot = SLOT_MIN;
 }
 }
 
 
-void *memdebug_malloc(size_t size) {
+void *memdebug_malloc(gravity_vm *vm, size_t size) {
+    #pragma unused(vm)
 	void *ptr = malloc(size);
 	void *ptr = malloc(size);
 	if (!ptr) {
 	if (!ptr) {
 		BUILD_ERROR("Unable to allocated a block of %zu bytes", size);
 		BUILD_ERROR("Unable to allocated a block of %zu bytes", size);
@@ -106,11 +123,13 @@ void *memdebug_malloc(size_t size) {
 	return ptr;
 	return ptr;
 }
 }
 
 
-void *memdebug_malloc0(size_t size) {
-	return memdebug_calloc(1, size);
+void *memdebug_malloc0(gravity_vm *vm, size_t size) {
+    #pragma unused(vm)
+	return memdebug_calloc(vm, 1, size);
 }
 }
 
 
-void *memdebug_calloc(size_t num, size_t size) {
+void *memdebug_calloc(gravity_vm *vm, size_t num, size_t size) {
+    #pragma unused(vm)
 	void *ptr = calloc(num, size);
 	void *ptr = calloc(num, size);
 	if (!ptr) {
 	if (!ptr) {
 		BUILD_ERROR("Unable to allocated a block of %zu bytes", size);
 		BUILD_ERROR("Unable to allocated a block of %zu bytes", size);
@@ -123,7 +142,8 @@ void *memdebug_calloc(size_t num, size_t size) {
 	return ptr;
 	return ptr;
 }
 }
 
 
-void *memdebug_realloc(void *ptr, size_t new_size) {
+void *memdebug_realloc(gravity_vm *vm, void *ptr, size_t new_size) {
+    #pragma unused(vm)
 	// ensure ptr has been previously allocated by malloc, calloc or realloc and not yet freed with free
 	// ensure ptr has been previously allocated by malloc, calloc or realloc and not yet freed with free
 	uint32_t index = _ptr_lookup(ptr);
 	uint32_t index = _ptr_lookup(ptr);
 	if (index == SLOT_NOTFOUND) {
 	if (index == SLOT_NOTFOUND) {
@@ -312,8 +332,8 @@ uint32_t _ptr_lookup (void *ptr) {
 
 
 char **_ptr_stacktrace (size_t *nframes) {
 char **_ptr_stacktrace (size_t *nframes) {
 	#if _WIN32
 	#if _WIN32
-	http://www.codeproject.com/Articles/11132/Walking-the-callstack
-	https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c/
+	// http://www.codeproject.com/Articles/11132/Walking-the-callstack
+	// https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c/
 	#else
 	#else
 	void *callstack[STACK_DEPTH];
 	void *callstack[STACK_DEPTH];
 	int n = backtrace(callstack, STACK_DEPTH);
 	int n = backtrace(callstack, STACK_DEPTH);

+ 36 - 27
src/shared/gravity_memory.h

@@ -12,46 +12,55 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <stdbool.h>
+#include <strings.h>
 
 
-// memory debugger must be turned on ONLY with GuardMalloc ON
-#define GRAVITY_MEMORY_DEBUG		0
+// memory debugger must be turned on ONLY with Xcode GuardMalloc ON
+#define GRAVITY_MEMORY_DEBUG            0
+
+#ifndef GRAVITY_VM_DEFINED
+#define GRAVITY_VM_DEFINED
+typedef struct gravity_vm				gravity_vm;
+#endif
 
 
 #if GRAVITY_MEMORY_DEBUG
 #if GRAVITY_MEMORY_DEBUG
-#define mem_init()					memdebug_init()
-#define mem_stat()					memdebug_stat()
-#define mem_alloc					memdebug_malloc0
-#define mem_calloc					memdebug_calloc
-#define mem_realloc					memdebug_realloc
-#define mem_free(v)					memdebug_free((void *)v)
-#define mem_check(v)				memdebug_setcheck(v)
-#define mem_status					memdebug_status
-#define mem_leaks()					memdebug_leaks()
-#define mem_remove					memdebug_remove
+#define mem_init()                      memdebug_init()
+#define mem_stat()                      memdebug_stat()
+#define mem_alloc(_vm,_size)            memdebug_malloc0(_vm,_size)
+#define mem_calloc(_vm,_count,_size)    memdebug_calloc(_vm,_count,_size)
+#define mem_realloc(_vm,_ptr,_size)     memdebug_realloc(_vm,_ptr,_size)
+#define mem_free(v)                     memdebug_free((void *)v)
+#define mem_check(v)                    memdebug_setcheck(v)
+#define mem_status                      memdebug_status
+#define mem_leaks()                     memdebug_leaks()
+#define mem_remove                      memdebug_remove
 #else
 #else
 #define mem_init()
 #define mem_init()
 #define mem_stat()
 #define mem_stat()
-#define mem_alloc(size)				calloc(1, size)
-#define mem_calloc					calloc
-#define mem_realloc					realloc
-#define mem_free(v)					free((void *)v)
+#define mem_alloc(_vm,_size)            gravity_calloc(_vm, 1, _size)
+#define mem_calloc(_vm,_count,_size)	gravity_calloc(_vm, _count, _size)
+#define mem_realloc(_vm,_ptr,_size)     gravity_realloc(_vm, _ptr, _size)
+#define mem_free(v)                     free((void *)v)
 #define mem_check(v)
 #define mem_check(v)
-#define mem_status()				0
-#define mem_leaks()					0
+#define mem_status()                    0
+#define mem_leaks()                     0
 #define mem_remove(_v)
 #define mem_remove(_v)
 #endif
 #endif
 
 
 #if GRAVITY_MEMORY_DEBUG
 #if GRAVITY_MEMORY_DEBUG
-void	memdebug_init(void);
-void	*memdebug_malloc(size_t size);
-void	*memdebug_malloc0(size_t size);
-void	*memdebug_calloc(size_t num, size_t size);
-void	*memdebug_realloc(void *ptr, size_t new_size);
-void	memdebug_free(void *ptr);
+void	memdebug_init (void);
+void	*memdebug_malloc (gravity_vm *vm, size_t size);
+void	*memdebug_malloc0 (gravity_vm *vm, size_t size);
+void	*memdebug_calloc (gravity_vm *vm, size_t num, size_t size);
+void	*memdebug_realloc (gravity_vm *vm, void *ptr, size_t new_size);
+void	memdebug_free (void *ptr);
 size_t	memdebug_leaks (void);
 size_t	memdebug_leaks (void);
 size_t	memdebug_status (void);
 size_t	memdebug_status (void);
-void	memdebug_setcheck(bool flag);
-void	memdebug_stat(void);
-bool	memdebug_remove(void *ptr);
+void	memdebug_setcheck (bool flag);
+void	memdebug_stat (void);
+bool	memdebug_remove (void *ptr);
+#else
+void    *gravity_calloc (gravity_vm *vm, size_t count, size_t size);
+void    *gravity_realloc (gravity_vm *vm, void *ptr, size_t new_size);
 #endif
 #endif
 
 
 #endif
 #endif

+ 30 - 30
src/shared/gravity_value.c

@@ -82,7 +82,7 @@ static void gravity_hash_gray (gravity_hash_t *table, gravity_value_t key, gravi
 // MARK: -
 // MARK: -
 
 
 gravity_module_t *gravity_module_new (gravity_vm *vm, const char *identifier) {
 gravity_module_t *gravity_module_new (gravity_vm *vm, const char *identifier) {
-	gravity_module_t *m = (gravity_module_t *)mem_alloc(sizeof(gravity_module_t));
+	gravity_module_t *m = (gravity_module_t *)mem_alloc(NULL, sizeof(gravity_module_t));
 	assert(m);
 	assert(m);
 
 
 	m->isa = gravity_class_module;
 	m->isa = gravity_class_module;
@@ -131,7 +131,7 @@ bool gravity_class_grow (gravity_class_t *c, uint32_t n) {
 	if (c->ivars) mem_free(c->ivars);
 	if (c->ivars) mem_free(c->ivars);
 	if (c->nivars + n >= MAX_IVARS) return false;
 	if (c->nivars + n >= MAX_IVARS) return false;
 	c->nivars += n;
 	c->nivars += n;
-	c->ivars = (gravity_value_t *)mem_alloc(c->nivars * sizeof(gravity_value_t));
+	c->ivars = (gravity_value_t *)mem_alloc(NULL, c->nivars * sizeof(gravity_value_t));
 	for (uint32_t i=0; i<c->nivars; ++i) c->ivars[i] = VALUE_FROM_NULL;
 	for (uint32_t i=0; i<c->nivars; ++i) c->ivars[i] = VALUE_FROM_NULL;
 	return true;
 	return true;
 }
 }
@@ -153,7 +153,7 @@ bool gravity_class_setsuper (gravity_class_t *baseclass, gravity_class_t *superc
 }
 }
 
 
 gravity_class_t *gravity_class_new_single (gravity_vm *vm, const char *identifier, uint32_t nivar) {
 gravity_class_t *gravity_class_new_single (gravity_vm *vm, const char *identifier, uint32_t nivar) {
-	gravity_class_t *c = (gravity_class_t *)mem_alloc(sizeof(gravity_class_t));
+	gravity_class_t *c = (gravity_class_t *)mem_alloc(NULL, sizeof(gravity_class_t));
 	assert(c);
 	assert(c);
 
 
 	c->isa = gravity_class_class;
 	c->isa = gravity_class_class;
@@ -162,7 +162,7 @@ gravity_class_t *gravity_class_new_single (gravity_vm *vm, const char *identifie
 	c->nivars = nivar;
 	c->nivars = nivar;
 	c->htable = gravity_hash_create(0, gravity_value_hash, gravity_value_equals, gravity_hash_keyfree, NULL);
 	c->htable = gravity_hash_create(0, gravity_value_hash, gravity_value_equals, gravity_hash_keyfree, NULL);
 	if (nivar) {
 	if (nivar) {
-		c->ivars = (gravity_value_t *)mem_alloc(nivar * sizeof(gravity_value_t));
+		c->ivars = (gravity_value_t *)mem_alloc(NULL, nivar * sizeof(gravity_value_t));
 		for (uint32_t i=0; i<nivar; ++i) c->ivars[i] = VALUE_FROM_NULL;
 		for (uint32_t i=0; i<nivar; ++i) c->ivars[i] = VALUE_FROM_NULL;
 	}
 	}
 
 
@@ -457,7 +457,7 @@ void gravity_class_blacken (gravity_vm *vm, gravity_class_t *c) {
 // MARK: -
 // MARK: -
 
 
 gravity_function_t *gravity_function_new (gravity_vm *vm, const char *identifier, uint16_t nparams, uint16_t nlocals, uint16_t ntemps, void *code) {
 gravity_function_t *gravity_function_new (gravity_vm *vm, const char *identifier, uint16_t nparams, uint16_t nlocals, uint16_t ntemps, void *code) {
-	gravity_function_t *f = (gravity_function_t *)mem_alloc(sizeof(gravity_function_t));
+	gravity_function_t *f = (gravity_function_t *)mem_alloc(NULL, sizeof(gravity_function_t));
 	assert(f);
 	assert(f);
 
 
 	f->isa = gravity_class_function;
 	f->isa = gravity_class_function;
@@ -581,7 +581,7 @@ static void gravity_function_bytecode_serialize (gravity_function_t *f, json_t *
 
 
 	uint32_t ninst = f->ninsts;
 	uint32_t ninst = f->ninsts;
 	uint32_t length = ninst * 2 * sizeof(uint32_t);
 	uint32_t length = ninst * 2 * sizeof(uint32_t);
-	uint8_t *hexchar = (uint8_t*) mem_alloc(sizeof(uint8_t) * length);
+	uint8_t *hexchar = (uint8_t*) mem_alloc(NULL, sizeof(uint8_t) * length);
 
 
 	for (uint32_t k=0, i=0; i < ninst; ++i) {
 	for (uint32_t k=0, i=0; i < ninst; ++i) {
 		uint32_t value = f->bytecode[i];
 		uint32_t value = f->bytecode[i];
@@ -598,7 +598,7 @@ static void gravity_function_bytecode_serialize (gravity_function_t *f, json_t *
 
 
 uint32_t *gravity_bytecode_deserialize (const char *buffer, size_t len, uint32_t *n) {
 uint32_t *gravity_bytecode_deserialize (const char *buffer, size_t len, uint32_t *n) {
 	uint32_t ninst = (uint32_t)len / 8;
 	uint32_t ninst = (uint32_t)len / 8;
-	uint32_t *bytecode = (uint32_t *)mem_alloc(sizeof(uint32_t) * (ninst + 1));	// +1 to get a 0 terminated bytecode (0 is opcode RET0)
+	uint32_t *bytecode = (uint32_t *)mem_alloc(NULL, sizeof(uint32_t) * (ninst + 1));	// +1 to get a 0 terminated bytecode (0 is opcode RET0)
 
 
 	for (uint32_t j=0; j<ninst; ++j) {
 	for (uint32_t j=0; j<ninst; ++j) {
 		register uint32_t v = 0;
 		register uint32_t v = 0;
@@ -633,7 +633,7 @@ uint32_t *gravity_bytecode_deserialize (const char *buffer, size_t len, uint32_t
 	return bytecode;
 	return bytecode;
 
 
 abort_conversion:
 abort_conversion:
-	*n = 0;
+    *n = 0;
 	if (bytecode) mem_free(bytecode);
 	if (bytecode) mem_free(bytecode);
 	return NULL;
 	return NULL;
 }
 }
@@ -849,11 +849,11 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
             if (value->type == json_null) {
             if (value->type == json_null) {
                 // if function is empty then just one RET0 implicit bytecode instruction
                 // if function is empty then just one RET0 implicit bytecode instruction
                 f->ninsts = 0;
                 f->ninsts = 0;
-                f->bytecode = (uint32_t *)mem_alloc(sizeof(uint32_t) * (f->ninsts + 1));
+                f->bytecode = (uint32_t *)mem_alloc(NULL, sizeof(uint32_t) * (f->ninsts + 1));
             } else {
             } else {
-			if (value->type != json_string) goto abort_load;
-            if (f->tag != EXEC_TYPE_NATIVE) goto abort_load;
-			f->bytecode = gravity_bytecode_deserialize(value->u.string.ptr, value->u.string.length, &f->ninsts);
+                if (value->type != json_string) goto abort_load;
+                if (f->tag != EXEC_TYPE_NATIVE) goto abort_load;
+                f->bytecode = gravity_bytecode_deserialize(value->u.string.ptr, value->u.string.length, &f->ninsts);
             }
             }
             bytecode_parsed = true;
             bytecode_parsed = true;
 			continue;
 			continue;
@@ -895,7 +895,7 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
 
 
 					case json_array: {
 					case json_array: {
 						uint32_t count = r->u.array.length;
 						uint32_t count = r->u.array.length;
-						gravity_list_t *list = gravity_list_new(NULL, count);
+						gravity_list_t *list = gravity_list_new (NULL, count);
                         if (!list) continue;
                         if (!list) continue;
 
 
 						for (uint32_t k=0; k<count; ++k) {
 						for (uint32_t k=0; k<count; ++k) {
@@ -949,7 +949,7 @@ void gravity_function_free (gravity_vm *vm, gravity_function_t *f) {
 		if (f->bytecode) mem_free((void *)f->bytecode);
 		if (f->bytecode) mem_free((void *)f->bytecode);
 		// DO NOT FREE EACH INDIVIDUAL CPOOL ITEM HERE
 		// DO NOT FREE EACH INDIVIDUAL CPOOL ITEM HERE
 		marray_destroy(f->cpool);
 		marray_destroy(f->cpool);
-	}
+    }
 	mem_free((void *)f);
 	mem_free((void *)f);
 }
 }
 
 
@@ -999,7 +999,7 @@ void gravity_function_blacken (gravity_vm *vm, gravity_function_t *f) {
 gravity_closure_t *gravity_closure_new (gravity_vm *vm, gravity_function_t *f) {
 gravity_closure_t *gravity_closure_new (gravity_vm *vm, gravity_function_t *f) {
 	#pragma unused(vm)
 	#pragma unused(vm)
 
 
-	gravity_closure_t *closure = (gravity_closure_t *)mem_alloc(sizeof(gravity_closure_t));
+	gravity_closure_t *closure = (gravity_closure_t *)mem_alloc(NULL, sizeof(gravity_closure_t));
 	assert(closure);
 	assert(closure);
 
 
 	closure->isa = gravity_class_closure;
 	closure->isa = gravity_class_closure;
@@ -1007,7 +1007,7 @@ gravity_closure_t *gravity_closure_new (gravity_vm *vm, gravity_function_t *f) {
 
 
 	// allocate upvalue array (+1 so I can simplify the iterator without the needs to access closure->f->nupvalues)
 	// allocate upvalue array (+1 so I can simplify the iterator without the needs to access closure->f->nupvalues)
 	uint16_t nupvalues = (f) ? f->nupvalues : 0;
 	uint16_t nupvalues = (f) ? f->nupvalues : 0;
-	closure->upvalue = (nupvalues) ? (gravity_upvalue_t **)mem_alloc(sizeof(gravity_upvalue_t*) * (f->nupvalues + 1)) : NULL;
+	closure->upvalue = (nupvalues) ? (gravity_upvalue_t **)mem_alloc(NULL, sizeof(gravity_upvalue_t*) * (f->nupvalues + 1)) : NULL;
 
 
 	if (vm) gravity_vm_transfer(vm, (gravity_object_t*)closure);
 	if (vm) gravity_vm_transfer(vm, (gravity_object_t*)closure);
 	return closure;
 	return closure;
@@ -1052,7 +1052,7 @@ void gravity_closure_blacken (gravity_vm *vm, gravity_closure_t *closure) {
 
 
 gravity_upvalue_t *gravity_upvalue_new (gravity_vm *vm, gravity_value_t *value) {
 gravity_upvalue_t *gravity_upvalue_new (gravity_vm *vm, gravity_value_t *value) {
 	#pragma unused(vm)
 	#pragma unused(vm)
-	gravity_upvalue_t *upvalue = (gravity_upvalue_t *)mem_alloc(sizeof(gravity_upvalue_t));
+	gravity_upvalue_t *upvalue = (gravity_upvalue_t *)mem_alloc(NULL, sizeof(gravity_upvalue_t));
 
 
 	upvalue->isa = gravity_class_upvalue;
 	upvalue->isa = gravity_class_upvalue;
 	upvalue->value = value;
 	upvalue->value = value;
@@ -1084,7 +1084,7 @@ void gravity_upvalue_free(gravity_vm *vm, gravity_upvalue_t *upvalue) {
 // MARK: -
 // MARK: -
 
 
 gravity_fiber_t *gravity_fiber_new (gravity_vm *vm, gravity_closure_t *closure, uint32_t nstack, uint32_t nframes) {
 gravity_fiber_t *gravity_fiber_new (gravity_vm *vm, gravity_closure_t *closure, uint32_t nstack, uint32_t nframes) {
-	gravity_fiber_t *fiber = (gravity_fiber_t *)mem_alloc(sizeof(gravity_fiber_t));
+	gravity_fiber_t *fiber = (gravity_fiber_t *)mem_alloc(NULL, sizeof(gravity_fiber_t));
 	assert(fiber);
 	assert(fiber);
 
 
 	fiber->isa = gravity_class_fiber;
 	fiber->isa = gravity_class_fiber;
@@ -1092,12 +1092,12 @@ gravity_fiber_t *gravity_fiber_new (gravity_vm *vm, gravity_closure_t *closure,
 	fiber->result = VALUE_FROM_NULL;
 	fiber->result = VALUE_FROM_NULL;
 
 
 	if (nstack < DEFAULT_MINSTACK_SIZE) nstack = DEFAULT_MINSTACK_SIZE;
 	if (nstack < DEFAULT_MINSTACK_SIZE) nstack = DEFAULT_MINSTACK_SIZE;
-	fiber->stack = (gravity_value_t *)mem_alloc(sizeof(gravity_value_t) * nstack);
+	fiber->stack = (gravity_value_t *)mem_alloc(NULL, sizeof(gravity_value_t) * nstack);
 	fiber->stacktop = fiber->stack;
 	fiber->stacktop = fiber->stack;
 	fiber->stackalloc = nstack;
 	fiber->stackalloc = nstack;
 
 
 	if (nframes < DEFAULT_MINCFRAME_SIZE) nframes = DEFAULT_MINCFRAME_SIZE;
 	if (nframes < DEFAULT_MINCFRAME_SIZE) nframes = DEFAULT_MINCFRAME_SIZE;
-	fiber->frames = (gravity_callframe_t *)mem_alloc(sizeof(gravity_callframe_t) * nframes);
+	fiber->frames = (gravity_callframe_t *)mem_alloc(NULL, sizeof(gravity_callframe_t) * nframes);
 	fiber->framesalloc = nframes;
 	fiber->framesalloc = nframes;
 	fiber->nframes = 1;
 	fiber->nframes = 1;
 
 
@@ -1358,7 +1358,7 @@ void gravity_object_blacken (gravity_vm *vm, gravity_object_t *obj) {
 // MARK: -
 // MARK: -
 
 
 gravity_instance_t *gravity_instance_new (gravity_vm *vm, gravity_class_t *c) {
 gravity_instance_t *gravity_instance_new (gravity_vm *vm, gravity_class_t *c) {
-	gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(sizeof(gravity_instance_t) + (c->nivars * sizeof(gravity_value_t)));
+	gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(NULL, sizeof(gravity_instance_t) + (c->nivars * sizeof(gravity_value_t)));
 
 
 	instance->isa = gravity_class_instance;
 	instance->isa = gravity_class_instance;
 	instance->objclass = c;
 	instance->objclass = c;
@@ -1371,7 +1371,7 @@ gravity_instance_t *gravity_instance_new (gravity_vm *vm, gravity_class_t *c) {
 gravity_instance_t *gravity_instance_dup (gravity_vm *vm, gravity_instance_t *src) {
 gravity_instance_t *gravity_instance_dup (gravity_vm *vm, gravity_instance_t *src) {
 	gravity_class_t *c = src->objclass;
 	gravity_class_t *c = src->objclass;
 
 
-	gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(sizeof(gravity_instance_t) + (c->nivars * sizeof(gravity_value_t)));
+	gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(NULL, sizeof(gravity_instance_t) + (c->nivars * sizeof(gravity_value_t)));
 	instance->objclass = c;
 	instance->objclass = c;
 	for (uint32_t i=0; i<c->nivars; ++i) instance->ivars[i] = src->ivars[i];
 	for (uint32_t i=0; i<c->nivars; ++i) instance->ivars[i] = src->ivars[i];
 
 
@@ -1500,7 +1500,7 @@ bool gravity_value_equals (gravity_value_t v1, gravity_value_t v2) {
         gravity_map_t *map1 = VALUE_AS_MAP(v1);
         gravity_map_t *map1 = VALUE_AS_MAP(v1);
         gravity_map_t *map2 = VALUE_AS_MAP(v2);
         gravity_map_t *map2 = VALUE_AS_MAP(v2);
         return gravity_hash_compare(map1->hash, map2->hash, hash_value_compare_cb, NULL);
         return gravity_hash_compare(map1->hash, map2->hash, hash_value_compare_cb, NULL);
-	}
+    }
 
 
 	// if here means that they are two heap allocated objects
 	// if here means that they are two heap allocated objects
 	gravity_object_t *obj1 = VALUE_AS_OBJECT(v1);
 	gravity_object_t *obj1 = VALUE_AS_OBJECT(v1);
@@ -1768,7 +1768,7 @@ void gravity_value_dump (gravity_vm *vm, gravity_value_t v, char *buffer, uint16
 gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n) {
 gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n) {
     if (n > MAX_ALLOCATION) return NULL;
     if (n > MAX_ALLOCATION) return NULL;
 
 
-	gravity_list_t *list = (gravity_list_t *)mem_alloc(sizeof(gravity_list_t));
+	gravity_list_t *list = (gravity_list_t *)mem_alloc(NULL, sizeof(gravity_list_t));
 
 
 	list->isa = gravity_class_list;
 	list->isa = gravity_class_list;
 	marray_init(list->array);
 	marray_init(list->array);
@@ -1779,7 +1779,7 @@ gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n) {
 }
 }
 
 
 gravity_list_t *gravity_list_from_array (gravity_vm *vm, uint32_t n, gravity_value_t *p) {
 gravity_list_t *gravity_list_from_array (gravity_vm *vm, uint32_t n, gravity_value_t *p) {
-	gravity_list_t *list = (gravity_list_t *)mem_alloc(sizeof(gravity_list_t));
+	gravity_list_t *list = (gravity_list_t *)mem_alloc(NULL, sizeof(gravity_list_t));
 
 
 	list->isa = gravity_class_list;
 	list->isa = gravity_class_list;
 	marray_init(list->array);
 	marray_init(list->array);
@@ -1828,7 +1828,7 @@ void gravity_list_blacken (gravity_vm *vm, gravity_list_t *list) {
 
 
 // MARK: -
 // MARK: -
 gravity_map_t *gravity_map_new (gravity_vm *vm, uint32_t n) {
 gravity_map_t *gravity_map_new (gravity_vm *vm, uint32_t n) {
-	gravity_map_t *map = (gravity_map_t *)mem_alloc(sizeof(gravity_map_t));
+	gravity_map_t *map = (gravity_map_t *)mem_alloc(NULL, sizeof(gravity_map_t));
 
 
 	map->isa = gravity_class_map;
 	map->isa = gravity_class_map;
 	map->hash = gravity_hash_create(n, gravity_value_hash, gravity_value_equals, NULL, NULL);
 	map->hash = gravity_hash_create(n, gravity_value_hash, gravity_value_equals, NULL, NULL);
@@ -1901,7 +1901,7 @@ void gravity_map_blacken (gravity_vm *vm, gravity_map_t *map) {
 // MARK: -
 // MARK: -
 
 
 gravity_range_t *gravity_range_new (gravity_vm *vm, gravity_int_t from_range, gravity_int_t to_range, bool inclusive) {
 gravity_range_t *gravity_range_new (gravity_vm *vm, gravity_int_t from_range, gravity_int_t to_range, bool inclusive) {
-	gravity_range_t *range = mem_alloc(sizeof(gravity_range_t));
+	gravity_range_t *range = mem_alloc(NULL, sizeof(gravity_range_t));
 
 
 	range->isa = gravity_class_range;
 	range->isa = gravity_class_range;
 	range->from = from_range;
 	range->from = from_range;
@@ -1930,11 +1930,11 @@ void gravity_range_blacken (gravity_vm *vm, gravity_range_t *range) {
 // MARK: -
 // MARK: -
 
 
 inline gravity_value_t gravity_string_to_value (gravity_vm *vm, const char *s, uint32_t len) {
 inline gravity_value_t gravity_string_to_value (gravity_vm *vm, const char *s, uint32_t len) {
-	gravity_string_t *obj = mem_alloc(sizeof(gravity_string_t));
+	gravity_string_t *obj = mem_alloc(NULL, sizeof(gravity_string_t));
 	if (len == AUTOLENGTH) len = (uint32_t)strlen(s);
 	if (len == AUTOLENGTH) len = (uint32_t)strlen(s);
 
 
 	uint32_t alloc = MAXNUM(len+1, DEFAULT_MINSTRING_SIZE);
 	uint32_t alloc = MAXNUM(len+1, DEFAULT_MINSTRING_SIZE);
-	char *ptr = mem_alloc(alloc);
+	char *ptr = mem_alloc(NULL, alloc);
 	memcpy(ptr, s, len);
 	memcpy(ptr, s, len);
 
 
 	obj->isa = gravity_class_string;
 	obj->isa = gravity_class_string;
@@ -1952,7 +1952,7 @@ inline gravity_value_t gravity_string_to_value (gravity_vm *vm, const char *s, u
 }
 }
 
 
 inline gravity_string_t *gravity_string_new (gravity_vm *vm, char *s, uint32_t len, uint32_t alloc) {
 inline gravity_string_t *gravity_string_new (gravity_vm *vm, char *s, uint32_t len, uint32_t alloc) {
-	gravity_string_t *obj = mem_alloc(sizeof(gravity_string_t));
+	gravity_string_t *obj = mem_alloc(NULL, sizeof(gravity_string_t));
 	if (len == AUTOLENGTH) len = (uint32_t)strlen(s);
 	if (len == AUTOLENGTH) len = (uint32_t)strlen(s);
 
 
 	obj->isa = gravity_class_string;
 	obj->isa = gravity_class_string;

+ 11 - 6
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define GRAVITY_VERSION						"0.3.0"     // git tag 0.3.0
-#define GRAVITY_VERSION_NUMBER				0x000300    // git push --tags
+#define GRAVITY_VERSION						"0.3.5"     // git tag 0.3.5
+#define GRAVITY_VERSION_NUMBER				0x000305    // git push --tags
 #define GRAVITY_BUILD_DATE					__DATE__
 #define GRAVITY_BUILD_DATE					__DATE__
 
 
 #ifndef GRAVITY_ENABLE_DOUBLE
 #ifndef GRAVITY_ENABLE_DOUBLE
@@ -89,10 +89,10 @@ extern "C" {
 #ifndef GRAVITY_MAP_DOTSUGAR
 #ifndef GRAVITY_MAP_DOTSUGAR
 #define GRAVITY_MAP_DOTSUGAR				1			// if 1 then map objects can be accessed with both map[key] and map.key
 #define GRAVITY_MAP_DOTSUGAR				1			// if 1 then map objects can be accessed with both map[key] and map.key
 #endif
 #endif
-
+    
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #undef GRAVITY_COMPUTED_GOTO
 #undef GRAVITY_COMPUTED_GOTO
-#define GRAVITY_COMPUTED_GOTO 0 // MSVC does not support it
+#define GRAVITY_COMPUTED_GOTO               0           // MSVC does not support it
 #endif
 #endif
 
 
 #define MAIN_FUNCTION						"main"
 #define MAIN_FUNCTION						"main"
@@ -128,7 +128,7 @@ extern "C" {
 #define MAX_ALLOCATION                      4194304     // 1024 * 1024 * 4 (about 4 millions entry)
 #define MAX_ALLOCATION                      4194304     // 1024 * 1024 * 4 (about 4 millions entry)
 #define MAX_CCALLS                          100         // default maximum number of nested C calls
 #define MAX_CCALLS                          100         // default maximum number of nested C calls
 #define MAX_MEMORY_BLOCK                    157286400   // 150MB
 #define MAX_MEMORY_BLOCK                    157286400   // 150MB
-
+    
 #define DEFAULT_CONTEXT_SIZE				256			// default VM context entries (can grow)
 #define DEFAULT_CONTEXT_SIZE				256			// default VM context entries (can grow)
 #define DEFAULT_MINSTRING_SIZE				32			// minimum string allocation size
 #define DEFAULT_MINSTRING_SIZE				32			// minimum string allocation size
 #define DEFAULT_MINSTACK_SIZE				256			// sizeof(gravity_value_t) * 256	 = 16 * 256 => 4 KB
 #define DEFAULT_MINSTACK_SIZE				256			// sizeof(gravity_value_t) * 256	 = 16 * 256 => 4 KB
@@ -136,7 +136,7 @@ extern "C" {
 #define DEFAULT_CG_THRESHOLD				5*1024*1024 // 5MB
 #define DEFAULT_CG_THRESHOLD				5*1024*1024 // 5MB
 #define DEFAULT_CG_MINTHRESHOLD				1024*1024	// 1MB
 #define DEFAULT_CG_MINTHRESHOLD				1024*1024	// 1MB
 #define DEFAULT_CG_RATIO					0.5			// 50%
 #define DEFAULT_CG_RATIO					0.5			// 50%
-
+    
 #define MAXNUM(a,b)							((a) > (b) ? a : b)
 #define MAXNUM(a,b)							((a) > (b) ? a : b)
 #define MINNUM(a,b)							((a) < (b) ? a : b)
 #define MINNUM(a,b)							((a) < (b) ? a : b)
 #define EPSILON								0.000001
 #define EPSILON								0.000001
@@ -214,7 +214,12 @@ typedef marray_t(gravity_value_t)		gravity_value_r;		// array of values
 #define GRAVITY_HASH_DEFINED
 #define GRAVITY_HASH_DEFINED
 typedef struct gravity_hash_t			gravity_hash_t;			// forward declaration
 typedef struct gravity_hash_t			gravity_hash_t;			// forward declaration
 #endif
 #endif
+    
+#ifndef GRAVITY_VM_DEFINED
+#define GRAVITY_VM_DEFINED
 typedef struct gravity_vm				gravity_vm;				// vm is an opaque data type
 typedef struct gravity_vm				gravity_vm;				// vm is an opaque data type
+#endif
+    
 typedef bool (*gravity_c_internal)(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex);
 typedef bool (*gravity_c_internal)(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex);
 
 
 typedef enum {
 typedef enum {

+ 1 - 1
src/utils/gravity_debug.c

@@ -68,7 +68,7 @@ const char *gravity_disassemble (const char *bcode, uint32_t blen, bool deserial
 	// allocate a buffer big enought to fit all disassembled bytecode
 	// allocate a buffer big enought to fit all disassembled bytecode
 	// I assume that each instruction (each row) will be 256 chars long
 	// I assume that each instruction (each row) will be 256 chars long
 	balloc = ninsts * rowlen;
 	balloc = ninsts * rowlen;
-	buffer = mem_alloc(balloc);
+	buffer = mem_alloc(NULL, balloc);
 	if (!buffer) goto abort_disassemble;
 	if (!buffer) goto abort_disassemble;
 
 
 	// conversion loop
 	// conversion loop

+ 5 - 5
src/utils/gravity_json.c

@@ -82,10 +82,10 @@ struct json_t {
 };
 };
 
 
 json_t *json_new (void) {
 json_t *json_new (void) {
-	json_t *json = mem_alloc(sizeof(json_t));
+	json_t *json = mem_alloc(NULL, sizeof(json_t));
 	assert(json);
 	assert(json);
 
 
-	json->buffer = mem_alloc(JSON_MINSIZE);
+	json->buffer = mem_alloc(NULL, JSON_MINSIZE);
 	assert(json->buffer);
 	assert(json->buffer);
 
 
 	json->blen = JSON_MINSIZE;
 	json->blen = JSON_MINSIZE;
@@ -103,7 +103,7 @@ static void json_write_raw (json_t *json, const char *buffer, size_t len, bool e
 	// check buffer reallocation
 	// check buffer reallocation
 	size_t reqlen = json->bused + len + prettylen + escapelen + JSON_MINSIZE;
 	size_t reqlen = json->bused + len + prettylen + escapelen + JSON_MINSIZE;
 	if (reqlen >= json->blen) {
 	if (reqlen >= json->blen) {
-		json->buffer = mem_realloc(json->buffer, json->blen + reqlen);
+		json->buffer = mem_realloc(NULL, json->buffer, json->blen + reqlen);
 		assert(json->buffer);
 		assert(json->buffer);
 		json->blen += reqlen;
 		json->blen += reqlen;
 	}
 	}
@@ -135,7 +135,7 @@ static void json_write_escaped (json_t *json, const char *buffer, size_t len, bo
 		return;
 		return;
 	}
 	}
 
 
-	char	*new_buffer = mem_alloc (len*2);
+	char	*new_buffer = mem_alloc(NULL, len*2);
 	size_t	j = 0;
 	size_t	j = 0;
 	assert(new_buffer);
 	assert(new_buffer);
 
 
@@ -368,7 +368,7 @@ typedef struct
 static void * default_alloc (size_t size, int zero, void * user_data)
 static void * default_alloc (size_t size, int zero, void * user_data)
 {
 {
 	#pragma unused(zero, user_data)
 	#pragma unused(zero, user_data)
-	return mem_alloc(size);
+	return mem_alloc(NULL, size);
 	//return zero ? calloc (1, size) : malloc (size);
 	//return zero ? calloc (1, size) : malloc (size);
 }
 }
 
 

+ 6 - 5
src/utils/gravity_utils.c

@@ -141,7 +141,7 @@ const char *file_read(const char *path, size_t *len) {
 	fd = open(path, O_RDONLY);
 	fd = open(path, O_RDONLY);
 	if (fd < 0) goto abort_read;
 	if (fd < 0) goto abort_read;
 
 
-	buffer = (char *)mem_alloc((size_t)fsize + 1);
+	buffer = (char *)mem_alloc(NULL, (size_t)fsize + 1);
 	if (buffer == NULL) goto abort_read;
 	if (buffer == NULL) goto abort_read;
 	buffer[fsize] = 0;
 	buffer[fsize] = 0;
 
 
@@ -190,7 +190,7 @@ const char *file_buildpath (const char *filename, const char *dirpath) {
 	size_t len2 = strlen(dirpath);
 	size_t len2 = strlen(dirpath);
 	size_t len = len1+len2+2;
 	size_t len = len1+len2+2;
 
 
-	char *full_path = (char *)mem_alloc(len);
+	char *full_path = (char *)mem_alloc(NULL, len);
 	if (!full_path) return NULL;
 	if (!full_path) return NULL;
 
 
 	if ((len2) && (dirpath[len2-1] != '/'))
 	if ((len2) && (dirpath[len2-1] != '/'))
@@ -323,14 +323,15 @@ int string_cmp (const char *s1, const char *s2) {
 
 
 const char *string_dup (const char *s1) {
 const char *string_dup (const char *s1) {
 	size_t	len = (size_t)strlen(s1);
 	size_t	len = (size_t)strlen(s1);
-	char	*s = (char *)mem_alloc(len + 1);
-
+	char	*s = (char *)mem_alloc(NULL, len + 1);
+	if (!s) return NULL;
 	memcpy(s, s1, len);
 	memcpy(s, s1, len);
 	return s;
 	return s;
 }
 }
 
 
 const char *string_ndup (const char *s1, size_t n) {
 const char *string_ndup (const char *s1, size_t n) {
-	char *s = (char *)mem_alloc(n + 1);
+	char *s = (char *)mem_alloc(NULL, n + 1);
+    if (!s) return NULL;
 	memcpy(s, s1, n);
 	memcpy(s, s1, n);
 	return s;
 	return s;
 }
 }

+ 20 - 0
test/unittest/max_mem_block.gravity

@@ -0,0 +1,20 @@
+#unittest {
+    name: "Max memory block protection.";
+    error: RUNTIME;
+};
+
+func main () {
+    var s = "AAAAAAAAAAAAA";
+    
+    s = s+1000000
+    
+    var ret = ""
+    for (var c in s) {
+        if (c == "A") {
+            while(true) {
+                ret += ret+c;
+            }
+        }
+    }
+    return ret;
+}