#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__); }) @import("parsimonyLibrary/boot.mc") @{ program.objects = {}; program.objects.class = {}; program.objects.methods = {}; class() { program.objects.function = "class"; nil; } method(object_name) { program.objects.currentClassName = object_name; program.objects.function = "method"; nil; } constructor(object_name) { program.objects.currentClassName = object_name; program.objects.function = "constructor"; nil; } send(object, method) { rawSend = (`declaration send(obj, met);); rawSend.semicolon = null; rawSend.declarators[0].paramTypeL[0].identifier = object; rawSend.declarators[0].paramTypeL[2].identifier = method; treeCopy(rawSend); } everyExternalDeclaration(s) { if (program.objects.function == "class") { program.objects.class[program.last.name.identifier] = {}; for (i=length(program.last.declarationL); i>0; i--) { program.last.declarationL[i] = program.last.declarationL[i-1]; }; program.last.declarationL[0] = treeCopy(`declaration int class; ); program.objects.function = "none"; return s; } if (program.objects.function == "method") { intern(program.objects.methods, string(program.last.declarators.declarators.identifier)); for (i in program.objects.class) { if (string(i) == string(program.objects.currentClassName)) intern(program.objects.class[i], string(program.last.declarators.declarators.identifier)); } program.last.declarators.declarators.identifier = string(program.objects.currentClassName) + "_" + string(program.last.declarators.declarators.identifier); param = (`declaration struct __oop *__self; ); param.semicolon = null; if (length(s.declarators.paramTypeL) > 0) { append(s.declarators.paramTypeL, newComma()); append(s.declarators.paramTypeL, treeCopy(param)); } else { s.declarators.paramTypeL = {}; s.declarators.paramTypeL[0] = treeCopy(param); } tmp = {}; tmp[0] = (`declaration struct @@(newId(string(program.objects.currentClassName))) *self = (struct @@(newId(string(program.objects.currentClassName))) *) __self; ); s.compoundS.expression = treeCopy(fusion(tmp, s.compoundS.expression)); program.objects.function = "none"; return s; } if (program.objects.function == "constructor") { structDeclaration = (`declaration struct @@(newId(string(program.objects.currentClassName))) *self = calloc(1, sizeof *self); ); rawDeclaration = (`declaration class = findClass(@@(newText("\"" + string(program.objects.currentClassName) + "\""))); ); returnSTMT = (`statement return (struct __oop *) self; ); t = {}; append(t, structDeclaration); lhs = treeCopy(s.compoundS.expression[0].expression.lhs); lhs.rhs = rawDeclaration.declarators[0].lhs; rawDeclaration.declarators[0].lhs = lhs; append(s.compoundS.expression, rawDeclaration); append(s.compoundS.expression, returnSTMT); s.compoundS.expression = fusion(t, s.compoundS.expression); program.objects.function = "none"; return s; } if (s.declarators != null && s.declarators.declarators != null && string(s.declarators.declarators.identifier) == "main") { rawSelector = (`declaration int _selector_ = findSelector("foo"); ); rawClass = (`declaration int _class_ = findClass("foo"); ); t = {}; for (i in program.objects.methods) { rawSelector.declarators[0].lhs.identifier = "_selector_" + string(program.objects.methods[i]); rawSelector.declarators[0].rhs.paramTypeL[0].text[0].value = "\"" + string(program.objects.methods[i]) + "\""; append(t, treeCopy(rawSelector)); } classKeys = keys(program.objects.class); for (i in classKeys) { rawClass.declarators[0].lhs.identifier = "_class_" + string(classKeys[i]); rawClass.declarators[0].rhs.paramTypeL[0].text[0].value = "\"" + string(classKeys[i]) + "\""; append(t, treeCopy(rawClass)); } rawAddMethod = (`declaration addMethod(_class_, _selector_, foo); ); for (i in program.objects.class) { for (k in program.objects.class[i]) { newObject = treeCopy(rawAddMethod); newObject.declarators[0].paramTypeL[0].identifier = string(rawAddMethod.declarators[0].paramTypeL[0].identifier) + string(i); newObject.declarators[0].paramTypeL[2].identifier = string(rawAddMethod.declarators[0].paramTypeL[2].identifier) + string(program.objects.class[i][k]); newObject.declarators[0].paramTypeL[4].identifier = string(i) + "_" + string(program.objects.class[i][k]); append(t, treeCopy(newObject)); } } s.compoundS.expression = fusion(t, s.compoundS.expression); return s; } s; } nil; }