#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__); })
|
|
|
|
@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)
|
|
{
|
|
// program.mem = newId(string(object));
|
|
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 @(treeCopy(newId(string(program.objects.currentClassName)))) *self = (struct @(newId(string(program.objects.currentClassName))) *) __self;
|
|
);
|
|
/////////////////////// FIX ME /////////////////////////////// MAYBE CONTEXT WITH GLOBAL
|
|
// tmp[0].specifiers[0].name.identifier = string(program.objects.currentClassName);
|
|
// tmp[0].declarators[0].rhs.typeName.specifiers[0].name.identifier = string(program.objects.currentClassName);
|
|
s.compoundS.expression = treeCopy(fusion(tmp, s.compoundS.expression));
|
|
program.objects.function = "none";
|
|
return s;
|
|
}
|
|
if (program.objects.function == "constructor") {
|
|
rawDeclaration = (`declaration class = findClass("foo");
|
|
);
|
|
rawDeclaration.declarators[0].rhs.paramTypeL[0].text[0].value = "\"" + string(program.objects.currentClassName) + "\"";
|
|
size = length(s.compoundS.expression);
|
|
lhs = treeCopy(s.compoundS.expression[size-2].expression.lhs);
|
|
lhs.rhs = rawDeclaration.declarators[0].lhs;
|
|
rawDeclaration.declarators[0].lhs = lhs;
|
|
s.compoundS.expression[size] = s.compoundS.expression[size-1];
|
|
s.compoundS.expression[size-1] = rawDeclaration;
|
|
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;
|
|
}
|