@ -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; | |||
} |
@ -0,0 +1,134 @@ | |||
#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; | |||
} |
@ -0,0 +1,233 @@ | |||
// This example serves to illustrate the possibility | |||
// of adding the object aspect to C | |||
// using the everyExternalDeclaration function. | |||
#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__); }) | |||
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; i<nbLn; i++) { | |||
x.semicolon.comment.text = x.semicolon.comment.text + "\n"; | |||
} | |||
for (i = 0; i<tabs; i++) { | |||
x.semicolon.comment.text = x.semicolon.comment.text + " "; | |||
} | |||
x; | |||
} | |||
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) | |||
{ | |||
rmSemi(`declaration send(@@(newText(object)), @@(newText(method)));); | |||
} | |||
everyExternalDeclaration(s) | |||
{ | |||
/*********** Class function ************/ | |||
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] = `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; | |||
} |
@ -0,0 +1,221 @@ | |||
// This example serves to illustrate the possibility | |||
// of adding the object aspect to C | |||
// using the parseFrom primitive. | |||
#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__); }) | |||
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; i<nbLn; i++) { | |||
x.semicolon.comment.text = x.semicolon.comment.text + "\n"; | |||
} | |||
for (i = 0; i<tabs; i++) { | |||
x.semicolon.comment.text = x.semicolon.comment.text + " "; | |||
} | |||
x; | |||
} | |||
program.objects = {}; | |||
program.objects.class = {}; | |||
program.objects.methods = {}; | |||
class() | |||
{ | |||
exp = parseFrom("declaration"); | |||
program.objects.class[exp.specifiers[0].name.identifier] = {}; | |||
for (i=length(exp.specifiers[0].declarationL); i>0; 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; | |||
} |