瀏覽代碼

Added vm parameter to error reporting callbacks (in order to be able to show call stack). Fixed an issue related to NULL SILENT option.

Marco Bambini 7 年之前
父節點
當前提交
c3c652dbf2

+ 17 - 1
gravity.xcodeproj/project.pbxproj

@@ -315,7 +315,7 @@
 		A9506CE81E69AAEB009A0045 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0820;
+				LastUpgradeCheck = 0930;
 				ORGANIZATIONNAME = Creolabs;
 				TargetAttributes = {
 					A9506CEF1E69AAEB009A0045 = {
@@ -413,15 +413,23 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -460,15 +468,23 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;

+ 2 - 2
src/cli/gravity.c

@@ -26,8 +26,8 @@ static const char *input_file = NULL;
 static const char *output_file = DEFAULT_OUTPUT;
 static bool quiet_flag = false;
 
-static void report_error (error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
-	#pragma unused(xdata)
+static void report_error (gravity_vm *vm, error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
+	#pragma unused(vm, xdata)
 	const char *type = "N/A";
 	switch (error_type) {
 		case GRAVITY_ERROR_NONE: type = "NONE"; break;

+ 2 - 2
src/cli/unittest.c

@@ -37,7 +37,7 @@ static void unittest_cleanup (const char *target_file, test_data *data) {
 	#pragma unused(target_file,data)
 }
 
-static void	unittest_callback (error_type_t error_type, const char *description, const char *notes, gravity_value_t value, int32_t row, int32_t col, void *xdata) {
+static void	unittest_callback (gravity_vm *vm, error_type_t error_type, const char *description, const char *notes, gravity_value_t value, int32_t row, int32_t col, void *xdata) {
 	test_data *data = (test_data *)xdata;
 	data->expected_error = error_type;
 	data->expected_value = value;
@@ -50,7 +50,7 @@ static void	unittest_callback (error_type_t error_type, const char *description,
 
 // MARK: -
 
-static void callback_error (error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
+static void callback_error (gravity_vm *vm, error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
 	test_data *data = (test_data *)xdata;
 
 	if (data->processed == true) return; // ignore 2nd error

+ 1 - 1
src/compiler/gravity_codegen.c

@@ -86,7 +86,7 @@ static void report_error (gvisitor_t *self, gnode_t *node, const char *format, .
 	};
 
 	// finally call error callback
-	if (error_fn) error_fn(GRAVITY_ERROR_SEMANTIC, buffer, error_desc, data);
+	if (error_fn) error_fn(NULL, GRAVITY_ERROR_SEMANTIC, buffer, error_desc, data);
 	else printf("%s\n", buffer);
 }
 

+ 4 - 4
src/compiler/gravity_parser.c

@@ -186,7 +186,7 @@ static void report_error (gravity_parser_t *parser, error_type_t error_type, gto
 	};
 
 	// finally call error callback
-	if (error_fn) error_fn(error_type, buffer, error_desc, data);
+	if (error_fn) error_fn(NULL, error_type, buffer, error_desc, data);
 	else printf("%s\n", buffer);
 }
 
@@ -2009,7 +2009,7 @@ static gnode_t *parse_unittest_macro (gravity_parser_t *parser) {
 	// report unittest to delegate
 	if ((parser->delegate) && (parser->delegate->unittest_callback)) {
 		gravity_unittest_callback unittest_cb = parser->delegate->unittest_callback;
-		unittest_cb(expected_error, description, note, expected_value, expected_nrow, expected_ncol, parser->delegate->xdata);
+		unittest_cb(NULL, expected_error, description, note, expected_value, expected_nrow, expected_ncol, parser->delegate->xdata);
 	} else {
 		// it was unit test responsability to free expected_value but if no unit test delegate is set I should take care of it
 		gravity_value_free(NULL, expected_value);
@@ -2574,8 +2574,8 @@ static void parser_register_optional_classes (gravity_parser_t *parser) {
         uint32_t i = 0;
         while (list[i]) {
             const char *identifier = list[i];
-            gnode_t *decl = gnode_variable_create(NO_TOKEN, string_dup(identifier), NULL, 0, NULL, LAST_DECLARATION());
-            gnode_array_push(decls, decl);
+            gnode_t *decl_node = gnode_variable_create(NO_TOKEN, string_dup(identifier), NULL, 0, NULL, LAST_DECLARATION());
+            gnode_array_push(decls, decl_node);
             ++i;
         }
     }

+ 1 - 1
src/compiler/gravity_semacheck1.c

@@ -59,7 +59,7 @@ static void report_error (gvisitor_t *self, gnode_t *node, const char *format, .
 	};
 
 	// finally call error callback
-	if (error_fn) error_fn(GRAVITY_ERROR_SEMANTIC, buffer, error_desc, data);
+	if (error_fn) error_fn(NULL, GRAVITY_ERROR_SEMANTIC, buffer, error_desc, data);
 	else printf("%s\n", buffer);
 }
 

+ 1 - 1
src/compiler/gravity_semacheck2.c

@@ -80,7 +80,7 @@ static void report_error (gvisitor_t *self, error_type_t error_type, gnode_t *no
 	};
 
 	// finally call error callback
-	if (error_fn) error_fn(error_type, buffer, error_desc, data);
+	if (error_fn) error_fn(NULL, error_type, buffer, error_desc, data);
 	else printf("%s\n", buffer);
 }
 

+ 8 - 1
src/runtime/gravity_core.c

@@ -2513,8 +2513,15 @@ static bool operator_null_not (gravity_vm *vm, gravity_value_t *args, uint16_t n
 #if GRAVITY_NULL_SILENT
 static bool operator_null_silent (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm,args,nargs)
+    // every operation on NULL returns NULL
 	RETURN_VALUE(VALUE_FROM_NULL, rindex);
 }
+
+static bool operator_store_null_silent (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused(vm,args,nargs,rindex)
+    // do not touch any register, a store op on NULL is a NOP operation
+    return true;
+}
 #endif
 
 static bool operator_null_cmp (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
@@ -2893,7 +2900,7 @@ static void gravity_core_init (void) {
 	#if GRAVITY_NULL_SILENT
 	gravity_class_bind(gravity_class_null, GRAVITY_INTERNAL_EXEC_NAME, NEW_CLOSURE_VALUE(operator_null_silent));
 	gravity_class_bind(gravity_class_null, GRAVITY_INTERNAL_LOAD_NAME, NEW_CLOSURE_VALUE(operator_null_silent));
-	gravity_class_bind(gravity_class_null, GRAVITY_INTERNAL_STORE_NAME, NEW_CLOSURE_VALUE(operator_null_silent));
+	gravity_class_bind(gravity_class_null, GRAVITY_INTERNAL_STORE_NAME, NEW_CLOSURE_VALUE(operator_store_null_silent));
 	gravity_class_bind(gravity_class_null, GRAVITY_INTERNAL_NOTFOUND_NAME, NEW_CLOSURE_VALUE(operator_null_silent));
 	#endif
 

+ 34 - 16
src/runtime/gravity_vm.c

@@ -74,6 +74,35 @@ struct gravity_vm {
 	#endif
 };
 
+// MARK: - Debug -
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+static void gravity_stack_dump (gravity_fiber_t *fiber) {
+    uint32_t index = 0;
+    for (gravity_value_t *stack = fiber->stack; stack < fiber->stacktop; ++stack) {
+        printf("[%05d]\t", index++);
+        if (!stack->isa) {printf("\n"); continue;}
+        gravity_value_dump(NULL, *stack, NULL, 0);
+    }
+    if (index) printf("\n\n");
+}
+
+static void gravity_callframe_dump (gravity_fiber_t *fiber) {
+    printf("===========================\n");
+    printf("CALL FRAME\n");
+    printf("===========================\n");
+    for (uint32_t i = 0; i < fiber->nframes; ++i) {
+        gravity_callframe_t *frame = &fiber->frames[i];
+        const char *fname = (frame->closure->f->identifier) ? frame->closure->f->identifier : "N/A";
+        gravity_value_t self_value = frame->stackstart[0];
+        char buffer[256];
+        gravity_value_dump(NULL, self_value, buffer, sizeof(buffer));
+        printf("[%03d]\t%s\t(%s)\n", i, fname, buffer);
+    }
+}
+#pragma clang diagnostic pop
+
 // MARK: -
 
 static void report_runtime_error (gravity_vm *vm, error_type_t error_type, const char *format, ...) {
@@ -92,11 +121,13 @@ static void report_runtime_error (gravity_vm *vm, error_type_t error_type, const
 	gravity_error_callback error_cb = ((gravity_delegate_t *)vm->delegate)->error_callback;
 	if (error_cb) {
 		void *data = ((gravity_delegate_t *)vm->delegate)->xdata;
-		error_cb(error_type, buffer, ERROR_DESC_NONE, data);
+		error_cb(vm, error_type, buffer, ERROR_DESC_NONE, data);
 	} else {
 		printf("%s\n", buffer);
 		fflush(stdout);
 	}
+    
+    // gravity_callframe_dump(vm->fiber);
 }
 
 static void gravity_cache_setup (void) {
@@ -153,19 +184,6 @@ gravity_value_t gravity_vm_keyindex (gravity_vm *vm, uint32_t index) {
 	return cache[index];
 }
 
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-static void gravity_stack_dump (gravity_fiber_t *fiber) {
-	uint32_t index = 0;
-	for (gravity_value_t *stack = fiber->stack; stack < fiber->stacktop; ++stack) {
-		printf("[%05d]\t", index++);
-		if (!stack->isa) {printf("\n"); continue;}
-		gravity_value_dump(NULL, *stack, NULL, 0);
-	}
-	if (index) printf("\n\n");
-}
-#pragma clang diagnostic pop
-
 static inline gravity_callframe_t *gravity_new_callframe (gravity_vm *vm, gravity_fiber_t *fiber) {
 	#pragma unused(vm)
 
@@ -295,7 +313,7 @@ static void gravity_vm_loadclass (gravity_vm *vm, gravity_class_t *c) {
 	gravity_hash_transform(meta->htable, gravity_gc_transform, (void *)vm);
 }
 
-// MARK: Internals -
+// MARK: - Optionals -
 
 void gravity_opt_register (gravity_vm *vm) {
     GRAVITY_MATH_REGISTER(vm);
@@ -309,7 +327,7 @@ bool gravity_isopt_class (gravity_class_t *c) {
     return GRAVITY_ISMATH_CLASS(c);
 }
 
-// MARK: -
+// MARK: - MAIN EXECUTION -
 
 static bool gravity_vm_exec (gravity_vm *vm) {
 	DECLARE_DISPATCH_TABLE;

+ 4 - 4
src/shared/gravity_delegate.h

@@ -32,10 +32,10 @@ typedef struct {
 
 #define ERROR_DESC_NONE		(error_desc_t){0,0,0,0,NULL}
 
-typedef void				(*gravity_log_callback)	(const char *message, void *xdata);
-typedef void                (*gravity_log_clear) (void *xdata);
-typedef void				(*gravity_error_callback) (error_type_t error_type, const char *description, error_desc_t error_desc, void *xdata);
-typedef void				(*gravity_unittest_callback) (error_type_t error_type, const char *desc, const char *note, gravity_value_t value, int32_t row, int32_t col, void *xdata);
+typedef void				(*gravity_log_callback)	(gravity_vm *vm, const char *message, void *xdata);
+typedef void                (*gravity_log_clear) (gravity_vm *vm, void *xdata);
+typedef void				(*gravity_error_callback) (gravity_vm *vm, error_type_t error_type, const char *description, error_desc_t error_desc, void *xdata);
+typedef void				(*gravity_unittest_callback) (gravity_vm *vm, error_type_t error_type, const char *desc, const char *note, gravity_value_t value, int32_t row, int32_t col, void *xdata);
 typedef void				(*gravity_parser_callback) (void *token, void *xdata);
 typedef void                (*gravity_type_callback) (void *token, const char *type, void *xdata);
 typedef const char*			(*gravity_precode_callback) (void *xdata);

+ 11 - 0
src/shared/gravity_value.c

@@ -1838,6 +1838,17 @@ void *gravity_value_xdata (gravity_value_t value) {
 	return NULL;
 }
 
+const char *gravity_value_name (gravity_value_t value) {
+    if (VALUE_ISA_INSTANCE(value)) {
+        gravity_instance_t *instance = VALUE_AS_INSTANCE(value);
+        return instance->objclass->identifier;
+    } else if (VALUE_ISA_CLASS(value)) {
+        gravity_class_t *c = VALUE_AS_CLASS(value);
+        return c->identifier;
+    }
+    return NULL;
+}
+
 void gravity_value_dump (gravity_vm *vm, gravity_value_t v, char *buffer, uint16_t len) {
 	const char *type = NULL;
 	const char *value = NULL;

+ 4 - 3
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 #endif
 
-#define GRAVITY_VERSION						"0.4.5"     // git tag 0.4.5
-#define GRAVITY_VERSION_NUMBER				0x000405    // git push --tags
+#define GRAVITY_VERSION						"0.4.6"     // git tag 0.4.6
+#define GRAVITY_VERSION_NUMBER				0x000406    // git push --tags
 #define GRAVITY_BUILD_DATE					__DATE__
 
 #ifndef GRAVITY_ENABLE_DOUBLE
@@ -83,7 +83,7 @@ extern "C" {
 #endif
 
 #ifndef GRAVITY_NULL_SILENT
-#define GRAVITY_NULL_SILENT					0			// if 1 then messages sent to null does not produce any runtime error
+#define GRAVITY_NULL_SILENT					1			// if 1 then messages sent to null does not produce any runtime error
 #endif
 
 #ifndef GRAVITY_MAP_DOTSUGAR
@@ -486,6 +486,7 @@ GRAVITY_API void				gravity_value_serialize (gravity_value_t v, json_t *json);
 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 const char          *gravity_value_name (gravity_value_t value);
 GRAVITY_API void				gravity_value_blacken (gravity_vm *vm, gravity_value_t v);
 GRAVITY_API uint32_t			gravity_value_size (gravity_vm *vm, gravity_value_t v);