ソースを参照

update on the automatic creation of an object

develop-theo
Theo Souchon 2年前
コミット
b4dbb6575c
7個のファイルの変更448行の追加16行の削除
  1. +24
    -10
      ccmeta.leg
  2. +25
    -1
      parsimonyLibrary/boot.mc
  3. +134
    -0
      parsimonyLibrary/dynamicObject.c
  4. +223
    -0
      parsimonyLibrary/dynamicObject.mc
  5. +2
    -5
      tests-parsimony/objectExample.c
  6. +0
    -0
      tests-parsimony/projectExample.c
  7. +40
    -0
      tests-parsimony/realObject.c

+ 24
- 10
ccmeta.leg ファイルの表示

@ -396,6 +396,7 @@ oop new_C_functionDef(oop specifiers, oop declarator, oop declarationList, oop c
map_set(object, declarators_symbol, declarator); map_set(object, declarators_symbol, declarator);
map_set(object, declarationL_symbol,declarationList); map_set(object, declarationL_symbol,declarationList);
map_set(object, compoundS_symbol, compoundStatement); map_set(object, compoundS_symbol, compoundStatement);
map_set(program, intern("last"), object);
return object; return object;
} }
@ -1342,6 +1343,15 @@ oop everyExternalDeclaration(oop s)
return s; return s;
} }
oop ensureId(oop s)
{
if (!is(Map, s) || map_get(s, __proto___symbol) != C_id_proto) {
fprintf(stderr, "Meta expression did not return required Id\n");
exit(1);
}
return s;
}
%} %}
@ -1362,6 +1372,8 @@ error = EOL* < (!EOL .)* EOL* (!EOL .)* > &{ error(yytext), 1 }
idOpt = id | {$$=newNullObject()} idOpt = id | {$$=newNullObject()}
id = <ID> { $$= new_C_id(yytext) } - id = <ID> { $$= new_C_id(yytext) } -
| META_AT META_LPAREN m:meta_exp META_RPAREN { $$= ensureId(eval(globals,m)) } -
ID = <NAME> &{ !is_C_keyword(yytext) } ID = <NAME> &{ !is_C_keyword(yytext) }
name = <NAME> { $$= new_C_id(yytext) } - name = <NAME> { $$= new_C_id(yytext) } -
@ -1699,8 +1711,8 @@ structOrUnionSpecifier = s:structOrUnion
@{ C_scopeEnd() } @{ C_scopeEnd() }
| &{ C_scopeAbort() } | &{ C_scopeAbort() }
) )
# ..., or after the closing brace.
( b:attributeSpecifiers &{gnu} | {b=newNullObject()} )
# ..., or after the closing brace.
( b:attributeSpecifiers &{gnu} | {b=newNullObject()} )
| i:id {l=d=r=b=newNullObject()} | i:id {l=d=r=b=newNullObject()}
) { $$= new_C_structSpec(s, a, i, l, d, r, b) } ) { $$= new_C_structSpec(s, a, i, l, d, r, b) }
@ -2427,14 +2439,15 @@ META_FLOAT = < [-+]* [0-9]+ '.' [0-9]* ('e'[-+]*[0-9]+)? > { $$= make
#--------------------------------------------- Meta operator ----------------------------------------------# #--------------------------------------------- Meta operator ----------------------------------------------#
MO_OPERATION = META_BACKTICK ( MO_INITIALIZER i:initializer { $$= newUnary(Quote_proto ,i) }
| MO_CONSTANT c:constant { $$= newUnary(Quote_proto ,c) }
| MO_STATEMENT c:statement { $$= newUnary(Quote_proto ,c) }
| MO_INTEGER i:integerConstant { $$= newUnary(Quote_proto ,i) }
| MO_DECLARATION i:declaration { $$= newUnary(Quote_proto ,i) }
| MO_STRING i:stringLiteral { $$= newUnary(Quote_proto ,i) }
| MO_FUN i:functionDefinition { $$= newUnary(Quote_proto ,i) }
| MO_ED i:externalDeclaration{ $$= newUnary(Quote_proto ,i) }
MO_OPERATION = META_BACKTICK ( MO_INITIALIZER i:initializer { $$= newUnary(Quote_proto ,i) }
| MO_CONSTANT c:constant { $$= newUnary(Quote_proto ,c) }
| MO_STATEMENT c:statement { $$= newUnary(Quote_proto ,c) }
| MO_INTEGER i:integerConstant { $$= newUnary(Quote_proto ,i) }
| MO_DECLARATION i:declaration { $$= newUnary(Quote_proto ,i) }
| MO_STRING i:stringLiteral { $$= newUnary(Quote_proto ,i) }
| MO_FUN i:functionDefinition { $$= newUnary(Quote_proto ,i) }
| MO_ED i:externalDeclaration { $$= newUnary(Quote_proto ,i) }
| MO_EXPRESSION i:expression { $$= newUnary(Quote_proto ,i) }
) )
MO_INITIALIZER = 'initializer' ![(a-zA-Z0-9_] -- MO_INITIALIZER = 'initializer' ![(a-zA-Z0-9_] --
@ -2445,6 +2458,7 @@ MO_DECLARATION = 'declaration' ![(a-zA-Z0-9_] --
MO_STRING = 'string' ![(a-zA-Z0-9_] -- MO_STRING = 'string' ![(a-zA-Z0-9_] --
MO_FUN = 'fun' ![(a-zA-Z0-9_] -- MO_FUN = 'fun' ![(a-zA-Z0-9_] --
MO_ED = 'ed' ![(a-zA-Z0-9_] -- MO_ED = 'ed' ![(a-zA-Z0-9_] --
MO_EXPRESSION = 'expression' ![(a-zA-Z0-9_] --
#--------------------------------------------- Meta rules ----------------------------------------------# #--------------------------------------------- Meta rules ----------------------------------------------#

+ 25
- 1
parsimonyLibrary/boot.mc ファイルの表示

@ -15,7 +15,7 @@
} }
getId(x) { { identifier: x, __proto__: C_id }; } getId(x) { { identifier: x, __proto__: C_id }; }
getEnum(x) { { attributeL: null, expression: null, name: getId(x), __proto__: C_enum }; } getEnum(x) { { attributeL: null, expression: null, name: getId(x), __proto__: C_enum }; }
getComma() { { text: ",", comment: { text : " ", __proto__: Comment }, __proto__: Token }; } getComma() { { text: ",", comment: { text : " ", __proto__: Comment }, __proto__: Token }; }
@ -27,6 +27,30 @@
s[length(s)] = e; s[length(s)] = e;
} }
// 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;
}
fusion(s1, s2) {
for (i in s2) {
append(s1, s2[i]);
}
return s1;
// return treeCopy(s1);
}
// If g then we add a filter on the application of the function f to each element of seq // If g then we add a filter on the application of the function f to each element of seq
map(f, seq, g) { map(f, seq, g) {
out = {}; out = {};

+ 134
- 0
parsimonyLibrary/dynamicObject.c ファイルの表示

@ -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;
}

+ 223
- 0
parsimonyLibrary/dynamicObject.mc ファイルの表示

@ -0,0 +1,223 @@
#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)
{
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, getComma());
append(s.declarators.paramTypeL, treeCopy(param));
} else {
s.declarators.paramTypeL = {};
s.declarators.paramTypeL[0] = treeCopy(param);
}
tmp = {};
tmp[0] = (`declaration struct @(getId(string(program.objects.currentClassName))) *self = (struct @(getId(string(program.objects.currentClassName))) *) __self;
);
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));
// string(program.objects.currentClassName);
// s.declarators.paramTypeL
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;
}

+ 2
- 5
tests-parsimony/objectExample.c ファイルの表示

@ -3,7 +3,7 @@
typedef long long int_t; typedef long long int_t;
typedef long double flt_t; typedef long double flt_t;
@beginObject(typeName:"typeName", objectName:"objectName")
@beginObject()
struct Integer { struct Integer {
int_t i; int_t i;
@ -21,8 +21,5 @@ struct Symbol {
char *name; char *name;
}; };
struct foo {
char *name;
};
@endObject @endObject

tests-parsimony/projExample.c → tests-parsimony/projectExample.c ファイルの表示


+ 40
- 0
tests-parsimony/realObject.c ファイルの表示

@ -0,0 +1,40 @@
@import("parsimonyLibrary/dynamicObject.mc")
#include <math.h>
struct __oop { int class; };
typedef struct __oop *oop;
@class struct Point { double x, y; };
@constructor("Point") oop newPoint(double x, double y)
{
struct Point *p = calloc(1, sizeof *p); // auto
self->x = x;
self->y = y;
return self; // need to cast (struct __oop *) self
}
@method("Point") double magnitude()
{
printf("point method : %f\n", sqrt(self->x * self->x * self->y * self->y));
return sqrt(self->x * self->x * self->y * self->y);
}
@method("Point") double getX()
{
printf("point method : %f\n", self->x);
return self->x;
}
int main()
{
oop p = newPoint(3, 4);
@send("p", "magnitude");
return 0;
}

読み込み中…
キャンセル
保存