// This example serves to illustrate the possibility // of adding the object aspect to C // using the everyExternalDeclaration function. #include #include #include 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; iclass][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; iselector; } 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 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; }