Parcourir la source

Improved register protection cases. Added bridge equals callback. Added remove and indexOf methods to to the List class. Others minor improvements.

Marco Bambini il y a 8 ans
Parent
commit
316f264eb6

+ 7 - 1
src/compiler/gravity_codegen.c

@@ -1403,11 +1403,17 @@ static void visit_postfix_expr (gvisitor_t *self, gnode_postfix_expr_t *node) {
 			
 			if (is_super) ircode_add(code, LOADS, dest_register, target_register, index_register);
 			else ircode_add(code, (is_real_assigment) ? STORE : LOAD, dest_register, target_register, index_register);
-			if ((!is_real_assigment) && (i+1<count)) {
+			if (!is_real_assigment) {
+                if (i+1<count) {
 				uint32_t rtemp = ircode_register_pop_context_protect(code, true);
                 if (rtemp == REGISTER_ERROR) {
                     report_error(self, (gnode_t *)expr, "Unexpected register error.");
                     return;
+                }
+                } else {
+                    // last loop
+                    if (ircode_register_istemp(code, dest_register))
+                        ircode_register_protect_outside_context(code, dest_register);
                 }
 			}
 			

+ 47 - 9
src/runtime/gravity_core.c

@@ -498,7 +498,7 @@ static bool object_eqq (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
         RETURN_VALUE(VALUE_FROM_FALSE, rindex);
     
     // then compare value
-    RETURN_VALUE(VALUE_FROM_BOOL(gravity_value_equals(v1, v2)), rindex);
+    RETURN_VALUE(VALUE_FROM_BOOL(gravity_value_vm_equals(vm, v1, v2)), rindex);
 }
 
 static bool object_neqq (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
@@ -512,7 +512,7 @@ static bool object_neqq (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 static bool object_cmp (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	if (gravity_value_equals(GET_VALUE(0), GET_VALUE(1))) RETURN_VALUE(VALUE_FROM_INT(0), rindex);
+	if (gravity_value_vm_equals(vm, GET_VALUE(0), GET_VALUE(1))) RETURN_VALUE(VALUE_FROM_INT(0), rindex);
 	RETURN_VALUE(VALUE_FROM_INT(1), rindex);
 }
 
@@ -801,11 +801,31 @@ static bool list_contains (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 	register gravity_int_t i = 0;
  
 	while (i < count) {
-		if (gravity_value_equals(marray_get(list->array, i), element)) {
+		if (gravity_value_vm_equals(vm, marray_get(list->array, i), element)) {
 			result = VALUE_FROM_TRUE;
 			break;
 		 }
-		i++;
+		++i;
+	 }
+ 
+	RETURN_VALUE(result, rindex);
+}
+
+static bool list_indexOf (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused(vm, nargs)
+    gravity_list_t *list = VALUE_AS_LIST(GET_VALUE(0));
+    gravity_value_t element = GET_VALUE(1);
+    gravity_value_t result = VALUE_FROM_INT(-1);
+    
+    register uint32_t count = (uint32_t)marray_size(list->array);
+    register gravity_int_t i = 0;
+    
+    while (i < count) {
+        if (gravity_value_vm_equals(vm, marray_get(list->array, i), element)) {
+            result = VALUE_FROM_INT(i);
+            break;
+        }
+        ++i;
 	 }
  
 	RETURN_VALUE(result, rindex);
@@ -870,6 +890,22 @@ static bool list_pop (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uin
 	RETURN_VALUE(value, rindex);
 }
 	
+static bool list_remove (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused(nargs)
+    gravity_list_t *list = VALUE_AS_LIST(GET_VALUE(0));
+    if (!VALUE_ISA_INT(GET_VALUE(1))) RETURN_ERROR("Parameter must be of type Int.");
+    
+    gravity_int_t index = VALUE_AS_INT(GET_VALUE(1));
+    size_t count = marray_size(list->array);
+    if ((index < 0) || (index >= count)) RETURN_ERROR("Out of bounds index.");
+    
+    // remove an item means move others down
+    memmove(&list->array.p[index], &list->array.p[index+1], ((count-1)-index) * sizeof(gravity_value_t));
+    list->array.n -= 1;
+    
+    RETURN_VALUE(GET_VALUE(0), rindex);
+}
+
 static bool list_iterator (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
 	gravity_list_t	*list = VALUE_AS_LIST(GET_VALUE(0));
@@ -1761,12 +1797,12 @@ static bool string_count (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 	int count = 0;
 
 	// iterate through whole string
-	for (int i = 0; i < main_str->len; i++) {
+	for (int i = 0; i < main_str->len; ++i) {
 		if (main_str->s[i] == str_to_count->s[j]) {
 			// if the characters match and we are on the last character of the search
 			// string, then we have found a match
 			if (j == str_to_count->len - 1) {
-				count++;
+				++count;
 				j = 0;
 				continue;
 			}
@@ -1778,7 +1814,7 @@ static bool string_count (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 		}
 		// move forward in the search string if we found a match but we aren't
 		// finished checking all the characters of the search string yet
-		j++;
+		++j;
 	}
 
 	RETURN_VALUE(VALUE_FROM_INT(count), rindex);
@@ -1820,7 +1856,7 @@ static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 	// if no arguments passed, change the whole string to uppercase
 	if (nargs == 1) {
-		for (int i = 0; i <= main_str->len; i++) {
+		for (int i = 0; i <= main_str->len; ++i) {
 		 ret[i] = toupper(ret[i]);
 		}
 	}
@@ -1859,7 +1895,7 @@ static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 	// if no arguments passed, change the whole string to lowercase
 	if (nargs == 1) {
-		for (int i = 0; i <= main_str->len; i++) {
+		for (int i = 0; i <= main_str->len; ++i) {
 		 ret[i] = tolower(ret[i]);
 		}
 	}
@@ -2371,6 +2407,8 @@ static void gravity_core_init (void) {
 	gravity_class_bind(gravity_class_list, "push", NEW_CLOSURE_VALUE(list_push));
 	gravity_class_bind(gravity_class_list, "pop", NEW_CLOSURE_VALUE(list_pop));
 	gravity_class_bind(gravity_class_list, "contains", NEW_CLOSURE_VALUE(list_contains));
+    gravity_class_bind(gravity_class_list, "remove", NEW_CLOSURE_VALUE(list_remove));
+    gravity_class_bind(gravity_class_list, "indexOf", NEW_CLOSURE_VALUE(list_indexOf));
     // Meta
     gravity_class_t *list_meta = gravity_class_get_meta(gravity_class_list);
     gravity_class_bind(list_meta, GRAVITY_INTERNAL_EXEC_NAME, NEW_CLOSURE_VALUE(list_exec));

+ 1 - 1
src/runtime/gravity_vm.c

@@ -157,7 +157,7 @@ static void gravity_stack_dump (gravity_fiber_t *fiber) {
 	for (gravity_value_t *stack = fiber->stack; stack < fiber->stacktop; ++stack) {
 		printf("[%05d]\t", index++);
 		if (!stack->isa) {printf("\n"); continue;}
-		gravity_value_dump(*stack, NULL, 0);
+		gravity_value_dump(NULL, *stack, NULL, 0);
 	}
 	if (index) printf("\n\n");
 }

+ 2 - 0
src/shared/gravity_delegate.h

@@ -46,6 +46,7 @@ typedef bool				(*gravity_bridge_getvalue) (gravity_vm *vm, void *xdata, gravity
 typedef bool				(*gravity_bridge_setundef) (gravity_vm *vm, void *xdata, gravity_value_t target, const char *key, gravity_value_t value);
 typedef bool				(*gravity_bridge_getundef) (gravity_vm *vm, void *xdata, gravity_value_t target, const char *key, uint32_t vindex);
 typedef bool				(*gravity_bridge_execute)  (gravity_vm *vm, void *xdata, gravity_value_t args[], int16_t nargs, uint32_t vindex);
+typedef bool                (*gravity_bridge_equals) (gravity_vm *vm, void *obj1, void *obj2);
 typedef const char*         (*gravity_bridge_string) (gravity_vm *vm, void *xdata, uint32_t *len);
 typedef uint32_t			(*gravity_bridge_size) (gravity_vm *vm, gravity_object_t *obj);
 typedef void				(*gravity_bridge_free) (gravity_vm *vm, gravity_object_t *obj);
@@ -71,6 +72,7 @@ typedef struct {
 	gravity_bridge_getundef		bridge_getundef;		// getter not found
 	gravity_bridge_execute		bridge_execute;			// execute a method/function
     gravity_bridge_string       bridge_string;          // instance string conversion
+    gravity_bridge_equals       bridge_equals;          // check if two objects are equals
 	gravity_bridge_size			bridge_size;			// size of obj
 	gravity_bridge_free			bridge_free;			// free obj
 } gravity_delegate_t;

+ 1 - 1
src/shared/gravity_hash.c

@@ -153,7 +153,7 @@ static void table_dump (gravity_hash_t *hashtable, gravity_value_t key, gravity_
 	#pragma unused (hashtable, data)
 	const char *k = ((gravity_string_t *)key.p)->s;
 	printf("%-20s=>\t",k);
-	gravity_value_dump(value, NULL, 0);
+	gravity_value_dump(NULL, value, NULL, 0);
 }
 
 // MARK: -

+ 26 - 5
src/shared/gravity_value.c

@@ -1436,6 +1436,25 @@ static bool hash_value_compare_cb (gravity_value_t v1, gravity_value_t v2, void
     return gravity_value_equals(v1, v2);
 }
 
+bool gravity_value_vm_equals (gravity_vm *vm, gravity_value_t v1, gravity_value_t v2) {
+    bool result = gravity_value_equals(v1, v2);
+    if (result || !vm) return result;
+    
+    // sanity check
+    if (!(VALUE_ISA_INSTANCE(v1) && VALUE_ISA_INSTANCE(v2))) return false;
+    
+    // if here means that they are two heap allocated objects
+    gravity_instance_t *obj1 = (gravity_instance_t *)VALUE_AS_OBJECT(v1);
+    gravity_instance_t *obj2 = (gravity_instance_t *)VALUE_AS_OBJECT(v2);
+    
+    gravity_delegate_t *delegate = gravity_vm_delegate(vm);
+    if (delegate && obj1->xdata && obj2->xdata && delegate->bridge_equals) {
+        return delegate->bridge_equals(vm, obj1->xdata, obj2->xdata);
+    }
+    
+    return false;
+}
+
 bool gravity_value_equals (gravity_value_t v1, gravity_value_t v2) {
 	
 	// check same class
@@ -1653,7 +1672,7 @@ void *gravity_value_xdata (gravity_value_t value) {
 	return NULL;
 }
 
-void gravity_value_dump (gravity_value_t v, char *buffer, uint16_t len) {
+void gravity_value_dump (gravity_vm *vm, gravity_value_t v, char *buffer, uint16_t len) {
 	const char *type = NULL;
 	const char *value = NULL;
 	char		sbuffer[1024];
@@ -1706,13 +1725,15 @@ void gravity_value_dump (gravity_value_t v, char *buffer, uint16_t len) {
 		value = buffer;
 	} else if (v.isa == gravity_class_list) {
 		type = "LIST";
-		value = "N/A";
-		snprintf(buffer, len, "(%s) %s", type, value);
+		gravity_value_t sval = convert_value2string(vm, v);
+        gravity_string_t *s = VALUE_AS_STRING(sval);
+        snprintf(buffer, len, "(%s) %.*s (%p)", type, s->len, s->s, s);
 		value = buffer;
 	} else if (v.isa == gravity_class_map) {
 		type = "MAP";
-		value = "N/A";
-		snprintf(buffer, len, "(%s) %s", type, value);
+        gravity_value_t sval = convert_value2string(vm, v);
+        gravity_string_t *s = VALUE_AS_STRING(sval);
+        snprintf(buffer, len, "(%s) %.*s (%p)", type, s->len, s->s, s);
 		value = buffer;
 	} else if (v.isa == gravity_class_range) {
 		type = "RANGE";

+ 2 - 1
src/shared/gravity_value.h

@@ -444,12 +444,13 @@ GRAVITY_API uint32_t			gravity_instance_size (gravity_vm *vm, gravity_instance_t
 
 // MARK: - VALUE -
 GRAVITY_API bool				gravity_value_equals (gravity_value_t v1, gravity_value_t v2);
+GRAVITY_API bool                gravity_value_vm_equals (gravity_vm *vm, gravity_value_t v1, gravity_value_t v2);
 GRAVITY_API uint32_t			gravity_value_hash (gravity_value_t value);
 GRAVITY_API gravity_class_t		*gravity_value_getclass (gravity_value_t v);
 GRAVITY_API gravity_class_t		*gravity_value_getsuper (gravity_value_t v);
 GRAVITY_API void				gravity_value_free (gravity_vm *vm, gravity_value_t v);
 GRAVITY_API void				gravity_value_serialize (gravity_value_t v, json_t *json);
-GRAVITY_API void				gravity_value_dump (gravity_value_t v, char *buffer, uint16_t len);
+GRAVITY_API void				gravity_value_dump (gravity_vm *vm, gravity_value_t v, char *buffer, uint16_t len);
 GRAVITY_API bool				gravity_value_isobject (gravity_value_t v);
 GRAVITY_API void				*gravity_value_xdata (gravity_value_t value);
 GRAVITY_API void				gravity_value_blacken (gravity_vm *vm, gravity_value_t v);