Ejemplo n.º 1
0
Archivo: ngs.c Proyecto: Wingie/ngs
void print_exception(VM *vm, VALUE result) {
	// TODO: fprintf to stderr and teach dump_titled to optionally fprintf to stderr too
	printf("====== Exception of type '%s' ======\n", obj_to_cstring(NGS_TYPE_NAME(NORMAL_TYPE_INSTANCE_TYPE(result))));
	// TODO: maybe macro to iterate attributes
	VALUE fields = NGS_TYPE_FIELDS(NORMAL_TYPE_INSTANCE_TYPE(result));
	HASH_OBJECT_ENTRY *e;
	for(e=HASH_HEAD(fields); e; e=e->insertion_order_next) {
		if(obj_is_of_type(ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)], vm->Backtrace)) {
			printf("=== [ backtrace ] ===\n");
			// Backtrace.frames = [{"closure": ..., "ip": ...}, ...]
			VALUE backtrace = ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)];
			VALUE frames;
			assert(get_normal_type_instace_attribute(backtrace, make_string("frames"), &frames) == METHOD_OK);
			unsigned int i;
			for(i = 0; i < OBJ_LEN(frames); i++) {
				VALUE frame, resolved_ip, ip;
				frame = ARRAY_ITEMS(frames)[i];
				H(ip, frame, "ip");
				resolved_ip = resolve_ip(vm, (IP)(GET_INT(ip) - 1));
				if(IS_HASH(resolved_ip)) {
					VALUE file, first_line, first_column, last_line, last_column;
					HASH_OBJECT_ENTRY *closure_entry;
					char *closure_name = "<anonymous>";
					H(file, resolved_ip, "file");
					H(first_line, resolved_ip, "first_line");
					H(first_column, resolved_ip, "first_column");
					H(last_line, resolved_ip, "last_line");
					H(last_column, resolved_ip, "last_column");
					closure_entry = get_hash_key(frame, make_string("closure"));
					if(closure_entry && IS_CLOSURE(closure_entry->val) && (IS_HASH(CLOSURE_OBJ_ATTRS(closure_entry->val)))) {
						HASH_OBJECT_ENTRY *name_entry;
						name_entry = get_hash_key(CLOSURE_OBJ_ATTRS(closure_entry->val), make_string("name"));
						if(name_entry) {
							closure_name = obj_to_cstring(name_entry->val);
						}
					}
					// TODO: fix types
					printf("[Frame #%u] %s:%d:%d - %d:%d [in %s]\n", i, obj_to_cstring(file), (int) GET_INT(first_line), (int) GET_INT(first_column), (int) GET_INT(last_line), (int) GET_INT(last_column), closure_name);
				} else {
					printf("[Frame #%u] (no source location)\n", i);
				}
			}
			continue;
		}
		if(obj_is_of_type(ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)], vm->Exception)) {
			assert(IS_STRING(e->key));
			printf("---8<--- %s - start ---8<---\n", obj_to_cstring(e->key));
			print_exception(vm, ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]);
			printf("---8<--- %s - end ---8<---\n", obj_to_cstring(e->key));
			continue;
		}
		if(IS_STRING(e->key)) {
			dump_titled(obj_to_cstring(e->key), ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]);
		} else {
			// Should not happen
			dump_titled("attribute key", e->key);
			dump_titled("attribute value", ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]);
		}
	}
}
Ejemplo n.º 2
0
Archivo: obj.c Proyecto: hbcbh1999/ngs
static void _dump(VALUE v, int level) {
	char **symbols;
	void *symbols_buffer[1];
	VALUE *ptr;
	size_t i;
	HASH_OBJECT_ENTRY *e;
	HASH_OBJECT_ENTRY **buckets;

	if(IS_NULL(v))  { printf("%*s* null\n",    level << 1, ""); goto exit; }
	if(IS_TRUE(v))  { printf("%*s* true\n",    level << 1, ""); goto exit; }
	if(IS_FALSE(v)) { printf("%*s* false\n",   level << 1, ""); goto exit; }
	if(IS_UNDEF(v)) { printf("%*s* undef\n",   level << 1, ""); goto exit; }
	if(IS_KWARGS_MARKER(v)){ printf("%*s* kwargs marker\n",   level << 1, ""); goto exit; }

	if(IS_INT(v))   { printf("%*s* int %" VALUE_NUM_FMT "\n", level << 1, "", GET_INT(v)); goto exit; }
	if(IS_REAL(v))  { printf("%*s* real %g\n", level << 1, "", REAL_OBJECT_VAL(v)); goto exit; }

	if(IS_STRING(v)) {
		// TODO: properly handle
		//       1. non-printable characters
		//       2. zero character
		printf("%*s* string(len=%zu) %.*s\n", level << 1, "", OBJ_LEN(v), (int) OBJ_LEN(v), (char *)OBJ_DATA_PTR(v));
		goto exit;
	}

	if(IS_NATIVE_METHOD(v)) {
		symbols_buffer[0] = OBJ_DATA_PTR(v);
		symbols = backtrace_symbols(symbols_buffer, 1);
		printf("%*s* native method %s at %p req_params=%d\n", level << 1, "", symbols[0], OBJ_DATA_PTR(v), NATIVE_METHOD_OBJ_N_REQ_PAR(v));
		for(i=0; i<NATIVE_METHOD_OBJ_N_REQ_PAR(v); i++) {
			printf("%*s* required parameter %zu\n", (level+1) << 1, "", i+1);
			_dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+0], level+2);
			_dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+1], level+2);
		}
		goto exit;
	}

	if(IS_CLOSURE(v)) {
		printf("%*s* closure name=%s ip=%zu locals_including_params=%d req_params=%d opt_params=%d n_uplevels=%d params_flags=%d\n", level << 1, "",
			IS_NULL(CLOSURE_OBJ_NAME(v)) ? "(none)" : obj_to_cstring(CLOSURE_OBJ_NAME(v)),
			CLOSURE_OBJ_IP(v),
			CLOSURE_OBJ_N_LOCALS(v),
			CLOSURE_OBJ_N_REQ_PAR(v),
			CLOSURE_OBJ_N_OPT_PAR(v),
			CLOSURE_OBJ_N_UPLEVELS(v),
			CLOSURE_OBJ_PARAMS_FLAGS(v)
		);
		for(i=0; i<CLOSURE_OBJ_N_REQ_PAR(v); i++) {
			printf("%*s* required parameter %zu (name and type follow)\n", (level+1) << 1, "", i+1);
			_dump(CLOSURE_OBJ_PARAMS(v)[i*2+0], level+2);
			_dump(CLOSURE_OBJ_PARAMS(v)[i*2+1], level+2);
		}
		for(i=0; i<CLOSURE_OBJ_N_OPT_PAR(v); i++) {
			printf("%*s* optional parameter %zu (name, type and default value follow)\n", (level+1) << 1, "", i+1);
			_dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 0], level+2);
			_dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 1], level+2);
			_dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 2], level+2);
		}
		i = CLOSURE_OBJ_N_REQ_PAR(v)*2 + CLOSURE_OBJ_N_OPT_PAR(v)*3;
		if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_ARR_SPLAT) {
			printf("%*s* array splat parameter\n", (level+1) << 1, "");
			_dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2);
			_dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2);
			i+=3;
		}
		if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_HASH_SPLAT) {
			printf("%*s* hash splat parameter\n", (level+1) << 1, "");
			_dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2);
			_dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2);
			i+=3;
		}
		goto exit;
	}

	if(IS_ARRAY(v)) {
		printf("%*s* array of length %zu\n", level << 1, "", OBJ_LEN(v));
		for(i=0, ptr=(VALUE *)OBJ_DATA_PTR(v); i<OBJ_LEN(v); i++, ptr++) {
			_dump(*ptr, level+1);
		}
		goto exit;
	}

	if(IS_HASH(v)) {
		printf("%*s* hash with total of %zu items in %zu buckets at %p\n", level << 1, "", OBJ_LEN(v), HASH_BUCKETS_N(v), OBJ_DATA_PTR(v));
		buckets = OBJ_DATA_PTR(v);
		for(i=0; i<HASH_BUCKETS_N(v); i++) {
			if(!buckets[i]) { continue; }
			printf("%*s* bucket # %zu\n", (level+1) << 1, "", i);
			for(e=buckets[i]; e; e=e->bucket_next) {
				printf("%*s* item at %p with hash() of %u insertion_order_prev=%p insertion_order_next=%p \n", (level+2) << 1, "", (void *)e, e->hash, (void *)e->insertion_order_prev, (void *)e->insertion_order_next);
				printf("%*s* key\n", (level+3) << 1, "");
				_dump(e->key, level+4);
				printf("%*s* value\n", (level+3) << 1, "");
				_dump(e->val, level+4);
			}
		}
		goto exit;
	}

	if(IS_NGS_TYPE(v)) {
		printf("%*s* type (name and optionally constructors and parents follow) id=%" PRIdPTR " ptr=%p\n", level << 1, "", NGS_TYPE_ID(v), IS_NORMAL_TYPE(v) ? v.ptr : 0);
		_dump(NGS_TYPE_NAME(v), level + 1);
		if(level < 3) {
			_dump(NGS_TYPE_FIELDS(v), level + 1);
			_dump(NGS_TYPE_CONSTRUCTORS(v), level + 1);
			_dump(NGS_TYPE_PARENTS(v), level + 1);
		}
		goto exit;
	}

	if(IS_CLIB(v)) {
		printf("%*s* C library (name follows) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v));
		_dump(CLIB_OBJECT_NAME(v), level + 1);
		goto exit;
	}

	if(IS_CSYM(v)) {
		printf("%*s* C symbol (name and libraray follow) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v));
		_dump(CSYM_OBJECT_NAME(v), level + 1);
		_dump(CSYM_OBJECT_LIB(v), level + 1);
		goto exit;
	}

	if(IS_NORMAL_TYPE_CONSTRUCTOR(v)) {
		printf("%*s* user type constructor (type optionally follows)\n", level << 1, "");
		if(level < 3) {
			_dump(OBJ_DATA(v), level + 1);
		}
		goto exit;
	}

	if(IS_NORMAL_TYPE_INSTANCE(v)) {
		printf("%*s* user type instance (type and fields optionally follow)\n", level << 1, "");
		// level < 4 so that uncaught exception ImplNotFound could display the type of the arguments
		if(level < 4) {
			_dump(NORMAL_TYPE_INSTANCE_TYPE(v), level + 1);
			_dump(NORMAL_TYPE_INSTANCE_FIELDS(v), level + 1);
		}
		goto exit;
	}

	printf("%*s* (dump not implemented for the object at %p)\n", level << 1, "", OBJ_DATA_PTR(v));

exit:
	return;
}