C compiler with embedded metalanguage.
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

134 wiersze
2.8 KiB

#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;
};
void *Object_print()
{
printf("Object\n");
return 0;
}
struct Point {
int class;
double x, y;
};
void *Point_print(struct Point *self)
{
printf("Point(%f, %f)\n", self->x, self->y);
return 0;
}
#define send(R, M, ...) ({ struct Object *__ = (struct Object *)(R); lookup(__->class, _selector_##M)(__, ##__VA_ARGS__); })
int main()
{
int _selector_print = findSelector("print" );
int _class_object = findClass ("Object" );
int _class_point = findClass ("Point" );
addMethod(_class_object, _selector_print, Object_print);
struct Object *o = calloc(1, sizeof(*o));
o->class = _class_object;
send(o, print);
addMethod(_class_point, _selector_print, Point_print);
struct Point *p = calloc(1, sizeof(*p));
p->class = _class_point;
send(p, print);
return 0;
}