Add constructor and method compiling
This commit is contained in:
parent
4919968250
commit
cb1b41c249
|
@ -125,8 +125,8 @@ SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call) {
|
||||||
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
||||||
if(d == NULL)
|
if(d == NULL)
|
||||||
notdeclared(call->name, call->debug);
|
notdeclared(call->name, call->debug);
|
||||||
if(d->subroutclass == function) {
|
if(d->subroutclass != method) {
|
||||||
eprintf("Calling a function as if it were a method; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
eprintf("Calling a function/constructor as if it were a method; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
|
|
|
@ -132,9 +132,15 @@ LINEBLOCK* pushtrue() {
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* pushthis() {
|
||||||
|
char* pushthis[] = { "push", "pointer", "0" };
|
||||||
|
return mklnblk(mksimpleln(pushthis, strcount(pushthis)));
|
||||||
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) {
|
LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) {
|
||||||
if(!strcmp(t->string, "true")) return pushtrue();
|
if(!strcmp(t->string, "true")) return pushtrue();
|
||||||
if(!strcmp(t->string, "false")) return pushfalse();
|
if(!strcmp(t->string, "false")) return pushfalse();
|
||||||
|
if(!strcmp(t->string, "this")) return pushthis();
|
||||||
eprintf("Unsupported keyword '%s'\n", t->string);
|
eprintf("Unsupported keyword '%s'\n", t->string);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -195,10 +201,15 @@ LINEBLOCK* compilecallln(SCOPE* s, SUBROUTCALL* call) {
|
||||||
|
|
||||||
// temporary ignore list for OS functions
|
// temporary ignore list for OS functions
|
||||||
char* ignoresubroutdecs[] = {
|
char* ignoresubroutdecs[] = {
|
||||||
"printInt", "void", "peek", "int", "poke", "void"
|
"printInt", "void", "peek", "int", "poke", "void", "deAlloc", "void", "setColor", "void", "drawRectangle", "void",
|
||||||
|
"wait", "void", "keyPressed", "char"
|
||||||
};
|
};
|
||||||
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
||||||
|
|
||||||
|
SUBROUTCLASS ignoreclasses[] = {
|
||||||
|
function, function, function, function, function, function, function, function
|
||||||
|
};
|
||||||
|
|
||||||
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
LINEBLOCK* blk = compilecallln(s, call);
|
LINEBLOCK* blk = compilecallln(s, call);
|
||||||
|
|
||||||
|
@ -209,15 +220,27 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
// therefore must be thrown away
|
// therefore must be thrown away
|
||||||
|
|
||||||
// gambiarra
|
// gambiarra
|
||||||
|
SUBROUTCLASS class;
|
||||||
char* type = NULL;
|
char* type = NULL;
|
||||||
for(int i = 0; i < ignorecount; i += 2) {
|
for(int i = 0; i < ignorecount; i += 2) {
|
||||||
if(!strcmp(call->name, ignoresubroutdecs[i])) {
|
if(!strcmp(call->name, ignoresubroutdecs[i])) {
|
||||||
type = ignoresubroutdecs[i+1];
|
type = ignoresubroutdecs[i+1];
|
||||||
|
class = ignoreclasses[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type == NULL)
|
if(type == NULL) {
|
||||||
type = getsubroutdecfromcall(s, call)->type;
|
SUBROUTDEC* dec = getsubroutdecfromcall(s, call);
|
||||||
|
type = dec->type;
|
||||||
|
class = dec->subroutclass;
|
||||||
|
}
|
||||||
|
if(class == method) {
|
||||||
|
// could be more efficient since getsubroutdecfromcall() gets the parent already
|
||||||
|
if(call->parentname == NULL)
|
||||||
|
blk = mergelnblks(pushthis(), blk);
|
||||||
|
else
|
||||||
|
blk = mergelnblks(pushvar(s, call->parentname), blk);
|
||||||
|
}
|
||||||
if(!strcmp(type, "void")) {
|
if(!strcmp(type, "void")) {
|
||||||
char* tokens[] = { "pop", "temp", "0" };
|
char* tokens[] = { "pop", "temp", "0" };
|
||||||
appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
||||||
|
@ -345,12 +368,17 @@ LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
|
LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd) {
|
||||||
LINE* label = mkline(3);
|
char* labelstrs[] = { "function", dotlabel(c->name, sd->name), itoa(countlocalvars(sd->body->vardecs)) };
|
||||||
addtoken(label, ezheapstr("function"));
|
LINE* label = mksimpleln(labelstrs, strcount(labelstrs));
|
||||||
addtoken(label, dotlabel(c->name, f->name));
|
free(labelstrs[1]);
|
||||||
addtoken(label, itoa(countlocalvars(f->body->vardecs)));
|
free(labelstrs[2]);
|
||||||
label->next = NULL;
|
label->next = NULL;
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
|
||||||
|
LINE* label = mksubdeclabel(c, f);
|
||||||
|
|
||||||
if(f->body->statements != NULL) {
|
if(f->body->statements != NULL) {
|
||||||
LINEBLOCK* body = compilefunbody(s, c, f->body);
|
LINEBLOCK* body = compilefunbody(s, c, f->body);
|
||||||
|
@ -361,6 +389,59 @@ LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
|
||||||
return mklnblk(label);
|
return mklnblk(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int countstrs(STRINGLIST* ls) {
|
||||||
|
int count = 0;
|
||||||
|
while(ls != NULL) {
|
||||||
|
count++;
|
||||||
|
ls = ls->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getobjsize(CLASS* c) {
|
||||||
|
CLASSVARDEC* curr = c->vardecs;
|
||||||
|
int count = 0;
|
||||||
|
while(curr != NULL) {
|
||||||
|
if(curr->type == field)
|
||||||
|
count += countstrs(curr->base->names);
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compileconstructor(SCOPE* s, CLASS* c, SUBROUTDEC* con) {
|
||||||
|
LINE* label = mksubdeclabel(c, con);
|
||||||
|
LINEBLOCK* blk = mklnblk(label);
|
||||||
|
|
||||||
|
char* size[] = { "push", itoa(getobjsize(c)) };
|
||||||
|
char* memalloc[] = { "call", "Memory.alloc", "1" };
|
||||||
|
char* poppointer[] = { "pop", "pointer", "0" };
|
||||||
|
appendln(blk, mksimpleln(size, strcount(size)));
|
||||||
|
appendln(blk, mksimpleln(memalloc, strcount(memalloc)));
|
||||||
|
appendln(blk, mksimpleln(poppointer, strcount(poppointer)));
|
||||||
|
free(size[1]);
|
||||||
|
|
||||||
|
if(con->body != NULL)
|
||||||
|
return mergelnblks(blk, compilefunbody(s, c, con->body));
|
||||||
|
else
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compilemethod(SCOPE* s, CLASS* c, SUBROUTDEC* m) {
|
||||||
|
LINE* label = mksubdeclabel(c, m);
|
||||||
|
LINEBLOCK* blk = mklnblk(label);
|
||||||
|
|
||||||
|
char* pusharg0[] = { "push", "argument" "0" };
|
||||||
|
char* poppointer[] = { "pop", "pointer", "0" };
|
||||||
|
appendln(blk, mksimpleln(pusharg0, strcount(pusharg0)));
|
||||||
|
appendln(blk, mksimpleln(poppointer, strcount(poppointer)));
|
||||||
|
|
||||||
|
if(m->body != NULL)
|
||||||
|
return mergelnblks(blk, compilefunbody(s, c, m->body));
|
||||||
|
else
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
|
LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
|
||||||
// 'this' and arguments are pushed by caller
|
// 'this' and arguments are pushed by caller
|
||||||
// Must have a 'return' at the end
|
// Must have a 'return' at the end
|
||||||
|
@ -373,6 +454,9 @@ LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
|
||||||
addparameters(myscope, sd->parameters);
|
addparameters(myscope, sd->parameters);
|
||||||
if(sd->subroutclass == function)
|
if(sd->subroutclass == function)
|
||||||
return compilefundec(myscope, c, sd);
|
return compilefundec(myscope, c, sd);
|
||||||
|
if(sd->subroutclass == constructor)
|
||||||
|
return compileconstructor(myscope, c, sd);
|
||||||
|
return compilemethod(myscope, c, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
||||||
|
|
Loading…
Reference in New Issue