extern "C" {
#include <stdbool.h>
#include <stdint.h>
}

#include <stdlib>

//------------------------------------------------------------------------------
//Declaration
trait allocator_c(otype T, otype allocator_t)
{
	void ctor(allocator_t* const);
	void dtor(allocator_t* const);
	void realloc(allocator_t* const, size_t);
	T* data(allocator_t* const);
};

forall(otype T, otype allocator_t | allocator_c(T, allocator_t))
struct vector
{
	allocator_t storage;
	size_t size;
};

int global = 3;

struct card_table_t
{
	size_t count;
	void* cards_start[100];
};

static inline void ctor(card_table_t* const this)
{
	this->count = 0;
}

struct gc_memory_pool
{
	struct memory_pool* mirror;
	struct memory_pool* next;

	uint8_t type_code;

	card_table_t* cards;

	uint8_t* end_p;
	uint8_t* free_p;
	uint8_t start_p[1];
};

void ctor(	gc_memory_pool *const this,
		size_t size,
		gc_memory_pool* next,
		gc_memory_pool* mirror,
		uint8_t type
	);

void dtor(gc_memory_pool *const this);

struct gc_pool_object_iterator
{
	struct gc_object_header* object;
	#ifndef NDEBUG
		intptr_t lower_limit;
		intptr_t upper_limit;
	#endif
};

void ctor(
		gc_pool_object_iterator* const this,
		void* start_object
		#ifndef NDEBUG
			, intptr_t pool_start
			, intptr_t pool_end
		#endif
	);

bool ?!=?(const gc_pool_object_iterator lhs, const gc_pool_object_iterator rhs);

gc_pool_object_iterator begin(gc_memory_pool* const this);
gc_pool_object_iterator end(gc_memory_pool* const);

gc_pool_object_iterator* ++?(gc_pool_object_iterator* it);

const void* *?(const gc_pool_object_iterator it);
void* *?(gc_pool_object_iterator it);

static inline bool gc_pool_is_from_space(const gc_memory_pool* pool)
{
	return false;
}

void gc_reset_pool(gc_memory_pool* const pool);

static inline size_t gc_pool_size_used(const gc_memory_pool* pool)
{
	return pool->free_p - pool->start_p;
}

static inline size_t gc_pool_size_total(const gc_memory_pool* pool)
{
	return pool->end_p - pool->start_p;
}

static inline size_t gc_pool_size_left(const gc_memory_pool* pool)
{
	return pool->end_p - pool->free_p;
}

void* gc_pool_allocate(gc_memory_pool* const pool, size_t size, bool zero);

gc_pool_object_iterator gc_pool_iterator_for(gc_memory_pool* const pool, void* member);

void ctor(gc_memory_pool *const this, size_t size, gc_memory_pool* next, gc_memory_pool* mirror, uint8_t type)
{
	this->mirror = mirror;
	this->next = next;
	this->type_code = type;

	this->cards = malloc();
	ctor(this->cards);

	this->end_p = ((uint8_t*)this) + size;
	this->free_p = this->start_p;

	// check(gc_pool_of(this) == this);
	// check(this->cards);
	// gc_reset_pool(this);
}
