From c4d102b9831cf94521847c902e2aedbdc85372ce Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Wed, 22 Mar 2023 18:48:22 +0900 Subject: [PATCH] Add boot and library meta code. --- src/parsimonyLibrary/boot.mc | 179 ++++++++++++++ src/parsimonyLibrary/dynamicObject.c | 134 ++++++++++ src/parsimonyLibrary/dynamicObjectExtDecl.mc | 233 ++++++++++++++++++ src/parsimonyLibrary/dynamicObjectParsFrom.mc | 221 +++++++++++++++++ 4 files changed, 767 insertions(+) create mode 100644 src/parsimonyLibrary/boot.mc create mode 100644 src/parsimonyLibrary/dynamicObject.c create mode 100644 src/parsimonyLibrary/dynamicObjectExtDecl.mc create mode 100644 src/parsimonyLibrary/dynamicObjectParsFrom.mc diff --git a/src/parsimonyLibrary/boot.mc b/src/parsimonyLibrary/boot.mc new file mode 100644 index 0000000..eace5df --- /dev/null +++ b/src/parsimonyLibrary/boot.mc @@ -0,0 +1,179 @@ +@{ + // create the function println + println(){ + apply(print, __arguments__); + print("\n"); + __arguments__; + } + + __requires__ = {}; + + // Import the file + require(__fileName__) + { + if (__requires__[__fileName__] != null) + { + return __requires__[__fileName__] + } + import(__fileName__); + __requires__[__fileName__] = scope(); + return scope(); + } + + // Get the current time in milliseconds + millis() + { + microseconds() / 1000; + } + + // Get the last element of s + last(s) + { + s[length(s) - 1]; + } + + // adding the element e at the end of the list l + append(s, e) + { + s[length(s)] = e; + } + + // adding the element e at the end of the list l + push(s, e) + { + append(s, e); + } + + // remove the last element of the list s or remove the element e if not null + pop(s, e) + { + if (e == null) + { + e = length(s) - 1 + } + ret = s[e]; + t = {}; + for (i in s) + { + if (i == e) + continue; + append(t, s[i]); + } + s = t; + ret; + } + + // add or don't change an element in a dictionnary + intern(s, e) + { + lo = 0; + hi = length(s) - 1; + while (lo <= hi) + { + mid = (lo + hi) / 2; + if (e > s[mid]) + lo = mid + 1; + else if (e < s[mid]) + hi = mid - 1; + else + return e; + } + for (i = length(s); i > lo; i = i - 1) + { + s[i] = s[i - 1]; + } + return s[lo] = e; + } + + // merge the two list s1 and s2 + fusion(s1, s2) + { + for (i in s2) + { + append(s1, s2[i]); + } + return s1; + } + + // If g then we add a filter on the application of the function f to each element of seq + map(f, seq, g) + { + out = {}; + if (!g) g = (){ 1 }; + for (i in seq) { + e = seq[i]; + out[length(out)] = g(e) ? f(e) : e ; + } + out; + } + + notToken(x){x.__proto__ != Token} + + // Select element e of s if the the result of the application of f on e is true + select(f, s) + { + out = {}; + for (i in s) + { + e = s[i]; + if (f(e)) + { + append(out, e); + } + } + out; + } + + // Select element e of s if the the result of the application of f on e is false + reject(f, s) + { + out = {}; + for (i in s) + { + e = s[i]; + if (!f(e)) + { + append(out, e); + } + } + out; + } + + //------------ C structure ------------// + + newId(x, comm) + { + if (comm == null) + { + {identifier : x, __proto__ : C_id}; + } + else + { + {identifier : x, comment : {text : comm, __proto__ : Comment}, __proto__ : C_id}; + } + } + + newText(x) { {value : x, __proto__ : C_string}; } + + newComment(com) { {text : com, __proto__ : Comment}; } + + newToken(txt, com) + { + if (com == null) return {text : txt, comment : newComment(""), __proto__ : Token}; + {text : txt, comment : newComment(com), __proto__ : Token}; + } + + newSemicolon(com){newToken(";", com)} + + newComma() { newToken(",", " "); } + + newStar(com) { newToken("*", com); } + + newBinary(com) { newToken("=", com); } + + newEnum(x) { {attributeL : null, expression : null, name : newId(x), __proto__ : C_enum}; } + + //-------------------- end ---------------------// + + nil; +} diff --git a/src/parsimonyLibrary/dynamicObject.c b/src/parsimonyLibrary/dynamicObject.c new file mode 100644 index 0000000..db7d5d1 --- /dev/null +++ b/src/parsimonyLibrary/dynamicObject.c @@ -0,0 +1,134 @@ +#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; +}; + +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; +} \ No newline at end of file diff --git a/src/parsimonyLibrary/dynamicObjectExtDecl.mc b/src/parsimonyLibrary/dynamicObjectExtDecl.mc new file mode 100644 index 0000000..a1c7fdf --- /dev/null +++ b/src/parsimonyLibrary/dynamicObjectExtDecl.mc @@ -0,0 +1,233 @@ +// 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; + +@import("../src/parsimonyLibrary/boot.mc") + +@{ + + rmSemi(x) { + x.semicolon = null; + x; + } + + makeln(x, tabs, newLine) { + x.semicolon.comment = newComment("\n"); + nbTabs = 0; + nbLn = 1; + if (tabs != null) { nbTabs = tabs; } + if (newLine != null) { nbLn = newLine; } + for (i = 1; i0; i--) { + program.last.declarationL[i] = program.last.declarationL[i-1]; + }; + program.last.declarationL[0] = `declaration int class; ; + program.objects.function = "none"; + return s; + } +/*********** Method function ************/ + if (program.objects.function == "method") { + intern(program.objects.methods, program.last.declarators.declarators.identifier); + for (i in program.objects.class) { + if (string(i) == program.objects.currentClassName) intern(program.objects.class[i], program.last.declarators.declarators.identifier); + } + program.last.declarators.declarators.identifier = program.objects.currentClassName + "_" + string(program.last.declarators.declarators.identifier); + param = rmSemi(`declaration struct __oop *__self;); + if (length(s.declarators.paramTypeL) > 0) { + append(s.declarators.paramTypeL, newComma()); + append(s.declarators.paramTypeL, param); + } else { + s.declarators.paramTypeL = {}; + s.declarators.paramTypeL[0] = param; + } + tmp = {}; + tmp[0] = makeln(`declaration struct @@(newId(program.objects.currentClassName, " ")) *self = (struct @@(newId(program.objects.currentClassName, " ")) *) __self;, 1); + s.compoundS.expression = fusion(tmp, s.compoundS.expression); + program.objects.function = "none"; + return s; + } +/*********** Constructor function ************/ + if (program.objects.function == "constructor") { + rawDeclaration = makeln(`declaration class = findClass(@@(newText("\"" + program.objects.currentClassName + "\"")));, 1); + t = {}; + append(t, makeln(`declaration struct @@(newId(program.objects.currentClassName, " ")) *self = calloc(1, sizeof *self);, 1)); + // take the structure of self->foo + lhs = treeCopy(s.compoundS.expression[0].expression.lhs); + lhs.rhs = newId("class", " "); + // Change foo to Class + rawDeclaration.declarators[0].lhs = lhs; + // prepare the right object to return + append(s.compoundS.expression, rawDeclaration); + append(s.compoundS.expression, makeln(`statement return (struct __oop *) self;)); + s.compoundS.expression = fusion(t, s.compoundS.expression); + program.objects.function = "none"; + return s; + } +/*********** Main function ************/ + if (s.declarators != null && s.declarators.declarators != null && string(s.declarators.declarators.identifier) == "main") { + t = {}; + for(i in program.objects.methods) { + methodName = string(program.objects.methods[i]); + append(t, makeln(`declaration int @@(newId("_selector_" + methodName)) = findSelector(@@(newId("\"" + methodName + "\"")));, 1)); + } + for (i in program.objects.class) { + className = string(i); + append(t, makeln(`declaration int @@(newId("_class_" + className)) = findClass(@@(newId("\"" + className + "\"")));, 1)); + for (k in program.objects.class[i]) { + linkedMethod = string(program.objects.class[i][k]); + castMethod = "(method_t) " + className + "_" + linkedMethod; + append(t, makeln(`declaration addMethod(@@(newId("_class_" + className)), @@(newId("_selector_" + linkedMethod)), @@(newId(castMethod)));, 1)); + } + } + s.compoundS.expression = fusion(t, s.compoundS.expression); + return s; + } + s; + } + + nil; +} diff --git a/src/parsimonyLibrary/dynamicObjectParsFrom.mc b/src/parsimonyLibrary/dynamicObjectParsFrom.mc new file mode 100644 index 0000000..dbd476a --- /dev/null +++ b/src/parsimonyLibrary/dynamicObjectParsFrom.mc @@ -0,0 +1,221 @@ +// This example serves to illustrate the possibility +// of adding the object aspect to C +// using the parseFrom primitive. + +#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; + +@import("../src/parsimonyLibrary/boot.mc") + +@{ + + rmSemi(x) { + x.semicolon = null; + x; + } + + makeln(x, tabs, newLine) { + x.semicolon.comment = newComment("\n"); + nbTabs = 0; + nbLn = 1; + if (tabs != null) { nbTabs = tabs; } + if (newLine != null) { nbLn = newLine; } + for (i = 1; i0; i--) { + exp.specifiers[0].declarationL[i] = exp.specifiers[0].declarationL[i-1]; + }; + exp.specifiers[0].declarationL[0] = `declaration int class; ; + exp; + } + + method() + { + id = string(parseFrom("id").identifier); + decl = parseFrom("func"); + intern(program.objects.methods, decl.declarators.declarators.identifier); + for (i in program.objects.class) { + if (string(i) == id) intern(program.objects.class[i], decl.declarators.declarators.identifier); + } + decl.declarators.declarators.identifier = id + "_" + string(decl.declarators.declarators.identifier); + param = rmSemi(`declaration struct __oop *__self;); + if (length(decl.declarators.paramTypeL) > 0) { + append(decl.declarators.paramTypeL, newComma()); + append(decl.declarators.paramTypeL, param); + } else { + decl.declarators.paramTypeL = {}; + decl.declarators.paramTypeL[0] = param; + } + tmp = {}; + tmp[0] = makeln(`declaration struct @@(newId(id, " ")) *self = (struct @@(newId(id, " ")) *) __self;, 1); + decl.compoundS.expression = fusion(tmp, decl.compoundS.expression); + program.objects.function = "none"; + decl; + } + + constructor() { + id = string(parseFrom("id").identifier); + decl = parseFrom("func"); + rawDeclaration = makeln(`declaration class = findClass(@@(newText("\"" + id + "\"")));, 1); + t = {}; + append(t, makeln(`declaration struct @@(newId(id, " ")) *self = calloc(1, sizeof *self);, 1)); + // take the structure of self->foo + lhs = treeCopy(decl.compoundS.expression[0].expression.lhs); + lhs.rhs = newId("class", " "); + // Change foo to Class + rawDeclaration.declarators[0].lhs = lhs; + // prepare the right object to return + append(decl.compoundS.expression, rawDeclaration); + append(decl.compoundS.expression, makeln(`statement return (struct __oop *) self;)); + decl.compoundS.expression = fusion(t, decl.compoundS.expression); + program.objects.function = "none"; + decl; + } + + // TODO + send() + { + nil; + } + + everyExternalDeclaration(s) + { +/*********** Main function ************/ + if (s.declarators != null && s.declarators.declarators != null && string(s.declarators.declarators.identifier) == "main") { + t = {}; + for(i in program.objects.methods) { + methodName = string(program.objects.methods[i]); + append(t, makeln(`declaration int @@(newId("_selector_" + methodName)) = findSelector(@@(newId("\"" + methodName + "\"")));, 1)); + } + for (i in program.objects.class) { + className = string(i); + append(t, makeln(`declaration int @@(newId("_class_" + className)) = findClass(@@(newId("\"" + className + "\"")));, 1)); + for (k in program.objects.class[i]) { + linkedMethod = string(program.objects.class[i][k]); + castMethod = "(method_t) " + className + "_" + linkedMethod; + append(t, makeln(`declaration addMethod(@@(newId("_class_" + className)), @@(newId("_selector_" + linkedMethod)), @@(newId(castMethod)));, 1)); + } + } + s.compoundS.expression = fusion(t, s.compoundS.expression); + return s; + } + s; + } + + nil; +}