# include "Point.h"
# include "Point.r"

#include <assert.h>

static void * Point_ctor (void * _self, va_list * app) {
	struct Point * self = super_ctor(Point, _self, app);

	self -> x = va_arg(* app, int);
	self -> y = va_arg(* app, int);
	return self;
}

static void Point_draw (const void * _self) {
	const struct Point * self = cast(Point, _self);

	printf("\".\" at %d,%d\n", self -> x, self -> y);
}

void move (void * _self, int dx, int dy) {
	struct Point * self = cast(Point, _self);

	self -> x += dx, self -> y += dy;
}

void draw (const void * _self) {
	const struct PointClass * class = cast(PointClass, classOf(_self));

	assert(class -> draw.method);
	((void (*) ()) class -> draw.method)(_self);
}

void super_draw (const void * _class, const void * _self) {
	const struct PointClass * superclass = cast(PointClass, super(_class));

	assert(superclass -> draw.method);
	((void (*) ()) superclass -> draw.method)(_self);
}

static void * PointClass_ctor (void * _self, va_list * app) {
	struct PointClass * self = super_ctor(PointClass, _self, app);
	Method selector;
	va_list ap = * app;

	while ((selector = va_arg(ap, Method)))
	{	const char * tag = va_arg(ap, const char *);
		Method method = va_arg(ap, Method);

		if (selector == (Method) draw)
		{	if (tag)
				self -> draw.tag = tag,
				self -> draw.selector = selector;
			self -> draw.method = method;
			continue;
		}
	}
	return self;
}

static const void * initPointClass (void)
{
	return ((struct Object *) PointClass) -> class ? PointClass :
		(PointClass = new(Class,
			"PointClass", Class, sizeof(struct PointClass),
			ctor, "", PointClass_ctor,
			(void *) 0));
}

static const struct ClassInit _PointClass = { { MAGIC }, initPointClass };
const void * PointClass = & _PointClass;

static const void * initPoint (void)
{
	return ((struct Object *) Point) -> class ? Point :
		(Point = new(PointClass,
			"Point", Object, sizeof(struct Point),
			ctor, "ctor", Point_ctor,
			draw, "draw", Point_draw,
			(void *) 0));
}

static const struct ClassInit _Point = { { MAGIC }, initPoint };
const void * Point = & _Point;
