// This example serves to illustrate the possibility
|
|
// of adding the object aspect to C
|
|
// using the parseFrom primitive.
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
struct Symbol {
|
|
char *name;
|
|
int class, selector;
|
|
};
|
|
|
|
struct Symbol *newSymbol(char *name)
|
|
{
|
|
struct Symbol *symbol = malloc(sizeof(*symbol));
|
|
symbol->name = strdup(name);
|
|
symbol->class = 0;
|
|
symbol->selector = 0;
|
|
return symbol;
|
|
}
|
|
|
|
struct Symbol **symbols = 0;
|
|
int nSymbols = 0;
|
|
|
|
struct Symbol *intern(char *name)
|
|
{
|
|
int lo = 0;
|
|
int hi = nSymbols - 1;
|
|
while (lo <= hi ) {
|
|
int mid = (lo+hi)/2;
|
|
int cmp = strcmp(name, symbols[mid]->name);
|
|
if (cmp > 0) lo = mid + 1;
|
|
else if (cmp < 0) hi = mid - 1;
|
|
else return symbols[mid];
|
|
}
|
|
symbols = realloc(symbols, sizeof(*symbols) * ++nSymbols);
|
|
memmove(symbols + lo + 1, symbols + lo, sizeof(*symbols)*(nSymbols - lo - 1));
|
|
return symbols[lo] = newSymbol(name);
|
|
}
|
|
|
|
typedef void *(*method_t)();
|
|
|
|
void *method_dnu()
|
|
{
|
|
printf("method not found\n");
|
|
exit(1);
|
|
return 0;
|
|
}
|
|
|
|
method_t **methods = 0;
|
|
int nClasses = 0;
|
|
int nSelectors = 0;
|
|
|
|
int ensureClass(struct Symbol *symbol)
|
|
{
|
|
if (symbol->class == 0) {
|
|
if (nClasses == 0) nClasses++;
|
|
symbol->class = nClasses++;
|
|
methods = realloc(methods, sizeof(*methods)*nClasses);
|
|
methods[symbol->class] = malloc(sizeof(*methods)*nSelectors);
|
|
for (int i = 0; i<nSelectors; ++i)
|
|
methods[symbol->class][i] = method_dnu;
|
|
}
|
|
return symbol->class;
|
|
}
|
|
|
|
int ensureSelector(struct Symbol *symbol)
|
|
{
|
|
if (symbol->selector == 0) {
|
|
if (nSelectors == 0) nSelectors++;
|
|
symbol->selector = nSelectors++;
|
|
for (int i = 0; i<nClasses; ++i) {
|
|
methods[i] = realloc(methods[i], sizeof(**methods)*nSelectors);
|
|
methods[i][nSelectors-1] = method_dnu;
|
|
}
|
|
}
|
|
return symbol->selector;
|
|
}
|
|
|
|
int findClass(char *class)
|
|
{
|
|
return ensureClass(intern(class));
|
|
}
|
|
|
|
int findSelector(char *selector)
|
|
{
|
|
return ensureSelector(intern(selector));
|
|
}
|
|
|
|
void addMethod(int class, int selector, method_t method)
|
|
{
|
|
methods[class][selector] = method;
|
|
}
|
|
|
|
#define lookup(C, S) (methods[C][S])
|
|
|
|
struct Object {
|
|
int class;
|
|
};
|
|
|
|
#define send(R, M, ...) ({ struct Object *__ = (struct Object *)(R); lookup(__->class, _selector_##M)(__, ##__VA_ARGS__); })
|
|
|
|
struct __oop { int class; };
|
|
|
|
typedef struct __oop *oop;
|
|
|
|
#include <math.h>
|
|
|
|
struct Point { int class; double x, y; };
|
|
|
|
oop newPoint(double x, double y)
|
|
{
|
|
struct Point *self = calloc(1, sizeof *self);
|
|
self->x = x;
|
|
self->y = y;
|
|
self->class = findClass("Point");
|
|
return (struct __oop *) self;
|
|
}
|
|
|
|
double Point_magnitude(struct __oop *__self)
|
|
{
|
|
struct Point *self = (struct Point *) __self;
|
|
printf("point method : %f\n", sqrt(self->x * self->x * self->y * self->y));
|
|
return sqrt(self->x * self->x * self->y * self->y);
|
|
}
|
|
|
|
double Point_getX(struct __oop *__self)
|
|
{
|
|
struct Point *self = (struct Point *) __self;
|
|
printf("point method : %f\n", self->x);
|
|
return self->x;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int _selector_getX= findSelector("getX");
|
|
int _selector_magnitude= findSelector("magnitude");
|
|
int _class_Point= findClass("Point");
|
|
addMethod(_class_Point, _selector_getX, (method_t) Point_getX);
|
|
addMethod(_class_Point, _selector_magnitude, (method_t) Point_magnitude);
|
|
oop p = newPoint(3, 4);
|
|
|
|
// @send p magnitude();
|
|
|
|
// @send p getX();
|
|
|
|
return 0;
|
|
}
|