Add operating system subroutine signatures
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "compiler-scopes.h"
|
||||
#include "os.h"
|
||||
|
||||
typedef enum { local, staticseg, arg, fieldseg } MEMSEGMENT;
|
||||
char* memsegnames[] = { "local", "static", "argument", "this" };
|
||||
@@ -16,7 +17,7 @@ CLASS* getclass(SCOPE* s, const char* name);
|
||||
SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name);
|
||||
SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call);
|
||||
SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call);
|
||||
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call);
|
||||
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call, VAR** varret);
|
||||
SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call);
|
||||
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
|
||||
|
||||
@@ -124,7 +125,7 @@ SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call) {
|
||||
CLASS* c = getclass(s, parent->type);
|
||||
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
||||
if(d == NULL)
|
||||
notdeclared(call->name, call->debug);
|
||||
return NULL;
|
||||
if(d->subroutclass != method) {
|
||||
eprintf("Calling a function/constructor as if it were a method; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||
exit(1);
|
||||
@@ -138,7 +139,7 @@ SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call) {
|
||||
notdeclared(call->parentname, call->debug);
|
||||
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
||||
if(d == NULL)
|
||||
notdeclared(call->name, call->debug);
|
||||
return NULL;
|
||||
if(d->subroutclass == method) {
|
||||
eprintf("Calling a method as if it were a function; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||
exit(1);
|
||||
@@ -146,26 +147,39 @@ SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call) {
|
||||
return d;
|
||||
}
|
||||
|
||||
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call) {
|
||||
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call, VAR** varret) {
|
||||
VAR* parent = getvar(s, call->parentname);
|
||||
if(parent != NULL)
|
||||
if(parent != NULL) {
|
||||
if(parent->primitive) {
|
||||
eprintf("Primitive type does not have subroutines; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||
exit(1);
|
||||
}
|
||||
*varret = parent;
|
||||
return getmethod(s, parent, call);
|
||||
else
|
||||
}
|
||||
else
|
||||
return getfunction(s, call);
|
||||
}
|
||||
|
||||
SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call) {
|
||||
SUBROUTDEC* d = getsubroutdecfromlist(s->currclass->subroutdecs, call->name);
|
||||
if(d == NULL)
|
||||
notdeclared(call->name, call->debug);
|
||||
return d;
|
||||
}
|
||||
|
||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
||||
if(call->parentname != NULL)
|
||||
return getsubroutdecwithparent(s, call);
|
||||
else
|
||||
return getsubroutdecwithoutparent(s, call);
|
||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call, VAR** varret) {
|
||||
SUBROUTDEC* d;
|
||||
*varret = NULL;
|
||||
if(call->parentname != NULL) {
|
||||
d = getossubroutdec(call);
|
||||
if(d == NULL)
|
||||
d = getsubroutdecwithparent(s, call, varret);
|
||||
}
|
||||
else {
|
||||
d = getsubroutdecwithoutparent(s, call);
|
||||
}
|
||||
if(d == NULL)
|
||||
notdeclared(call->name, call->debug);
|
||||
return d;
|
||||
}
|
||||
|
||||
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
|
||||
@@ -234,7 +248,7 @@ void addfield(SCOPE* s, CLASSVARDEC* v) {
|
||||
}
|
||||
|
||||
void addclassvardec(SCOPE* s, CLASSVARDEC* v) {
|
||||
if(v->type == staticseg)
|
||||
if(v->type == stat)
|
||||
addstaticvar(s, v);
|
||||
else
|
||||
addfield(s, v);
|
||||
|
@@ -43,7 +43,7 @@ void addparameters(SCOPE* s, PARAMETER* params);
|
||||
SCOPE* mkscope(SCOPE* prev);
|
||||
|
||||
// Single type getters
|
||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call, VAR** varret);
|
||||
CLASS* getclass(SCOPE* s, const char* name);
|
||||
|
||||
// Generic getters
|
||||
|
@@ -108,11 +108,18 @@ LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
|
||||
return blk;
|
||||
}
|
||||
|
||||
LINEBLOCK* opvar(SCOPE* s, char* op, const char* name) {
|
||||
VAR* v = getvar(s, name);
|
||||
LINEBLOCK* opvarraw(SCOPE* s, char* op, VAR* v) {
|
||||
char* tokens[] = { op, v->memsegment, itoa(v->index) };
|
||||
return mklnblk(mksimpleln(tokens, strcount(tokens)));
|
||||
}
|
||||
|
||||
LINEBLOCK* opvar(SCOPE* s, char* op, const char* name) {
|
||||
VAR* v = getvar(s, name);
|
||||
return opvarraw(s, op, v);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushvarraw(SCOPE*s, VAR* v) {
|
||||
return opvarraw(s, "push", v);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushvar(SCOPE* s, const char* name) {
|
||||
@@ -185,64 +192,39 @@ LINEBLOCK* compileexplist(SCOPE* s, EXPRESSIONLIST* explist) {
|
||||
return head;
|
||||
}
|
||||
|
||||
LINEBLOCK* compilecallln(SCOPE* s, SUBROUTCALL* call) {
|
||||
LINEBLOCK* compilecallln(SCOPE* s, SUBROUTDEC* d, SUBROUTCALL* call) {
|
||||
LINE* ln = mkline(3);
|
||||
|
||||
addtoken(ln, ezheapstr("call"));
|
||||
|
||||
if(call->parentname != NULL)
|
||||
addtoken(ln, dotlabel(call->parentname, call->name));
|
||||
else
|
||||
addtoken(ln, dotlabel(s->currclass->name, call->name));
|
||||
addtoken(ln, dotlabel(d->class->name, call->name));
|
||||
|
||||
addtoken(ln, itoa(countexpressions(call->parameters)));
|
||||
int count = countexpressions(call->parameters);
|
||||
if(d->subroutclass == method)
|
||||
count++;
|
||||
addtoken(ln, itoa(count));
|
||||
|
||||
return mklnblk(ln);
|
||||
}
|
||||
|
||||
// temporary ignore list for OS functions
|
||||
char* ignoresubroutdecs[] = {
|
||||
"printInt", "void", "peek", "int", "poke", "void", "deAlloc", "void", "setColor", "void", "drawRectangle", "void",
|
||||
"wait", "void", "keyPressed", "char"
|
||||
};
|
||||
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
||||
|
||||
SUBROUTCLASS ignoreclasses[] = {
|
||||
function, function, function, function, function, function, function, function
|
||||
};
|
||||
|
||||
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
||||
LINEBLOCK* blk = compilecallln(s, call);
|
||||
VAR* v;
|
||||
SUBROUTDEC* d = getsubroutdecfromcall(s, call, &v);
|
||||
LINEBLOCK* blk = compilecallln(s, d, call);
|
||||
|
||||
if(call->parameters != NULL)
|
||||
blk = mergelnblks(compileexplist(s, call->parameters), blk);
|
||||
|
||||
// void functions always return 0
|
||||
// therefore must be thrown away
|
||||
|
||||
// gambiarra
|
||||
SUBROUTCLASS class;
|
||||
char* type = NULL;
|
||||
for(int i = 0; i < ignorecount; i += 2) {
|
||||
if(!strcmp(call->name, ignoresubroutdecs[i])) {
|
||||
type = ignoresubroutdecs[i+1];
|
||||
class = ignoreclasses[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(type == NULL) {
|
||||
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(d->subroutclass == method) {
|
||||
if(call->parentname == NULL)
|
||||
blk = mergelnblks(pushthis(), blk);
|
||||
else
|
||||
blk = mergelnblks(pushvar(s, call->parentname), blk);
|
||||
blk = mergelnblks(pushvarraw(s, v), blk);
|
||||
}
|
||||
if(!strcmp(type, "void")) {
|
||||
|
||||
// void functions always return 0
|
||||
// therefore must be thrown away
|
||||
if(!strcmp(d->type, "void")) {
|
||||
char* tokens[] = { "pop", "temp", "0" };
|
||||
appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
||||
}
|
||||
@@ -418,13 +400,13 @@ LINEBLOCK* compileconstructor(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* con)
|
||||
LINE* label = mksubdeclabel(cl, con);
|
||||
LINEBLOCK* blk = mklnblk(label);
|
||||
|
||||
char* size[] = { "push", itoa(getobjsize(cl)) };
|
||||
char* size[] = { "push", "constant", itoa(getobjsize(cl)) };
|
||||
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]);
|
||||
free(size[2]);
|
||||
|
||||
if(con->body != NULL)
|
||||
return mergelnblks(blk, compilefunbody(c, s, cl, con->body));
|
||||
@@ -436,7 +418,7 @@ LINEBLOCK* compilemethod(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* m) {
|
||||
LINE* label = mksubdeclabel(cl, m);
|
||||
LINEBLOCK* blk = mklnblk(label);
|
||||
|
||||
char* pusharg0[] = { "push", "argument" "0" };
|
||||
char* pusharg0[] = { "push", "argument", "0" };
|
||||
char* poppointer[] = { "pop", "pointer", "0" };
|
||||
appendln(blk, mksimpleln(pusharg0, strcount(pusharg0)));
|
||||
appendln(blk, mksimpleln(poppointer, strcount(poppointer)));
|
||||
|
Reference in New Issue
Block a user