Add array accessing
This commit is contained in:
parent
2e86c2b9e5
commit
b9a553b107
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
FILES = *.c */*.c
|
||||
LIBRARIES = -lpthread
|
||||
INCLUDES = -I. -I./parser/ -I./compiler/ -I./vm/ -I./tokenizer/ -I./misc/
|
||||
CFLAGS = -std=c99 -g
|
||||
CFLAGS = -std=c99 -g -Wall
|
||||
OUTFILE = jack-compiler
|
||||
|
||||
main: ${FILES}
|
||||
|
|
|
@ -26,11 +26,11 @@ SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
|
|||
// Scope adding
|
||||
VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg, int i);
|
||||
void addvar(SCOPE* s, VAR** dest, VAR* v);
|
||||
void addlocalvar(SCOPE* s, VARDEC* v, int i);
|
||||
void addlocalvar(SCOPE* s, VARDEC* v, int* i);
|
||||
void addstaticvar(COMPILER* c, SCOPE* s, CLASSVARDEC* v);
|
||||
void addfield(SCOPE* s, CLASSVARDEC* v, int i);
|
||||
void addfield(SCOPE* s, CLASSVARDEC* v, int* i);
|
||||
void addclassvardec(COMPILER* c, SCOPE* s, CLASSVARDEC* v, int* i);
|
||||
void addparameter(SCOPE* s, PARAMETER* p, int i);
|
||||
void addparameter(SCOPE* s, PARAMETER* p, int* i);
|
||||
|
||||
// Error messages
|
||||
void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2) {
|
||||
|
@ -223,32 +223,33 @@ void addvar(SCOPE* s, VAR** dest, VAR* v) {
|
|||
*dest = v;
|
||||
}
|
||||
|
||||
void addlocalvar(SCOPE* s, VARDEC* v, int i) {
|
||||
void addlocalvar(SCOPE* s, VARDEC* v, int* i) {
|
||||
STRINGLIST* currname = v->names;
|
||||
while(currname != NULL) {
|
||||
addvar(s, &(s->localvars), mkvar(v->type, currname->content, v->primitive, v->debug, local, i));
|
||||
addvar(s, &(s->localvars), mkvar(v->type, currname->content, v->primitive, v->debug, local, *i));
|
||||
currname = currname->next;
|
||||
(*i)++;
|
||||
}
|
||||
}
|
||||
|
||||
void addstaticvar(COMPILER* c, SCOPE* s, CLASSVARDEC* v) {
|
||||
pthread_mutex_lock(&(c->staticmutex));
|
||||
static int count = 0;
|
||||
int i = count;
|
||||
count++;
|
||||
pthread_mutex_unlock(&(c->staticmutex));
|
||||
STRINGLIST* currname = v->base->names;
|
||||
pthread_mutex_lock(&(c->staticmutex));
|
||||
static int i = 0;
|
||||
while(currname != NULL) {
|
||||
addvar(s, &(s->staticvars), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, staticseg, i));
|
||||
currname = currname->next;
|
||||
i++;
|
||||
}
|
||||
pthread_mutex_unlock(&(c->staticmutex));
|
||||
}
|
||||
|
||||
void addfield(SCOPE* s, CLASSVARDEC* v, int i) {
|
||||
void addfield(SCOPE* s, CLASSVARDEC* v, int* i) {
|
||||
STRINGLIST* currname = v->base->names;
|
||||
while(currname != NULL) {
|
||||
addvar(s, &(s->fields), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, fieldseg, i));
|
||||
addvar(s, &(s->fields), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, fieldseg, *i));
|
||||
currname = currname->next;
|
||||
(*i)++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,13 +257,13 @@ void addclassvardec(COMPILER* c, SCOPE* s, CLASSVARDEC* v, int* i) {
|
|||
if(v->type == stat)
|
||||
addstaticvar(c, s, v);
|
||||
else {
|
||||
addfield(s, v, *i);
|
||||
*i++;
|
||||
addfield(s, v, i);
|
||||
}
|
||||
}
|
||||
|
||||
void addparameter(SCOPE* s, PARAMETER* p, int i) {
|
||||
addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg, i));
|
||||
void addparameter(SCOPE* s, PARAMETER* p, int* i) {
|
||||
addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg, *i));
|
||||
(*i)++;
|
||||
}
|
||||
|
||||
// Group adding
|
||||
|
@ -277,8 +278,7 @@ void addclassvardecs(COMPILER* c, SCOPE* s, CLASSVARDEC* classvardecs) {
|
|||
void addlocalvars(SCOPE* s, VARDEC* localvars) {
|
||||
int i = 0;
|
||||
while(localvars != NULL) {
|
||||
addlocalvar(s, localvars, i);
|
||||
i++;
|
||||
addlocalvar(s, localvars, &i);
|
||||
localvars = localvars->next;
|
||||
}
|
||||
}
|
||||
|
@ -286,8 +286,7 @@ void addlocalvars(SCOPE* s, VARDEC* localvars) {
|
|||
void addparameters(SCOPE* s, PARAMETER* params) {
|
||||
int i = 0;
|
||||
while(params != NULL) {
|
||||
addparameter(s, params, i);
|
||||
i++;
|
||||
addparameter(s, params, &i);
|
||||
params = params->next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,15 +85,13 @@ LINE* mathopln(char op) {
|
|||
char* tokens[] = { "call", "Math.divide", "2" };
|
||||
return mksimpleln(tokens, strcount(tokens));
|
||||
}
|
||||
if(op == '*') {
|
||||
char* tokens[] = { "call", "Math.multiply", "2" };
|
||||
return mksimpleln(tokens, strcount(tokens));
|
||||
}
|
||||
}
|
||||
|
||||
LINEBLOCK* pushconstant(int n) {
|
||||
LINE* pushconstant(int n) {
|
||||
char* tokens[] = { "push", "constant", itoa(n) };
|
||||
return mklnblk(mksimpleln(tokens, strcount(tokens)));
|
||||
return mksimpleln(tokens, strcount(tokens));
|
||||
}
|
||||
|
||||
LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
|
||||
|
@ -107,47 +105,77 @@ LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
|
|||
return blk;
|
||||
}
|
||||
|
||||
LINEBLOCK* opvarraw(SCOPE* s, char* op, VAR* v) {
|
||||
LINE* opvarraw(SCOPE* s, char* op, VAR* v) {
|
||||
char* tokens[] = { op, v->memsegment, itoa(v->index) };
|
||||
return mklnblk(mksimpleln(tokens, strcount(tokens)));
|
||||
return mksimpleln(tokens, strcount(tokens));
|
||||
}
|
||||
|
||||
LINEBLOCK* opvar(SCOPE* s, char* op, const char* name) {
|
||||
LINE* opvar(SCOPE* s, char* op, const char* name) {
|
||||
VAR* v = getvar(s, name);
|
||||
return opvarraw(s, op, v);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushvarraw(SCOPE*s, VAR* v) {
|
||||
LINE* pushvarraw(SCOPE*s, VAR* v) {
|
||||
return opvarraw(s, "push", v);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushvar(SCOPE* s, const char* name) {
|
||||
LINE* pushvar(SCOPE* s, const char* name) {
|
||||
return opvar(s, "push", name);
|
||||
}
|
||||
|
||||
LINEBLOCK* popvar(SCOPE* s, const char* name) {
|
||||
LINE* popvar(SCOPE* s, const char* name) {
|
||||
return opvar(s, "pop", name);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushfalse() {
|
||||
LINE* pushfalse() {
|
||||
return pushconstant(0);
|
||||
}
|
||||
|
||||
LINEBLOCK* pushtrue() {
|
||||
LINEBLOCK* blk = pushfalse();
|
||||
LINEBLOCK* blk = mklnblk(pushfalse());
|
||||
appendln(blk, onetoken("not"));
|
||||
return blk;
|
||||
}
|
||||
|
||||
LINEBLOCK* pushthis() {
|
||||
char* pushthis[] = { "push", "pointer", "0" };
|
||||
return mklnblk(mksimpleln(pushthis, strcount(pushthis)));
|
||||
LINE* pushthisadd() {
|
||||
char* pushthisadd[] = { "push", "pointer", "0" };
|
||||
return mksimpleln(pushthisadd, strcount(pushthisadd));
|
||||
}
|
||||
|
||||
LINE* popthatadd() {
|
||||
char* popthatadd[] = { "pop", "pointer", "1" };
|
||||
return mksimpleln(popthatadd, strcount(popthatadd));
|
||||
}
|
||||
|
||||
LINE* pushthatadd() {
|
||||
char* pushthatadd[] = { "push", "pointer", "1" };
|
||||
return mksimpleln(pushthatadd, strcount(pushthatadd));
|
||||
}
|
||||
|
||||
LINE* popthat() {
|
||||
char* popthat[] = { "pop", "that", "0" };
|
||||
return mksimpleln(popthat, strcount(popthat));
|
||||
}
|
||||
|
||||
LINE* pushthat() {
|
||||
char* pushthat[] = { "push", "that", "0" };
|
||||
return mksimpleln(pushthat, strcount(pushthat));
|
||||
}
|
||||
|
||||
LINE* pushtemp() {
|
||||
char* pushtemp[] = { "push", "temp", "0" };
|
||||
return mksimpleln(pushtemp, strcount(pushtemp));
|
||||
}
|
||||
|
||||
LINE* poptemp() {
|
||||
char* poptemp[] = { "pop", "temp", "0" };
|
||||
return mksimpleln(poptemp, strcount(poptemp));
|
||||
}
|
||||
|
||||
LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) {
|
||||
if(!strcmp(t->string, "true")) return pushtrue();
|
||||
if(!strcmp(t->string, "false")) return pushfalse();
|
||||
if(!strcmp(t->string, "this")) return pushthis();
|
||||
if(!strcmp(t->string, "false")) return mklnblk(pushfalse());
|
||||
if(!strcmp(t->string, "this")) return mklnblk(pushthisadd());
|
||||
eprintf("Unsupported keyword '%s'\n", t->string);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -185,16 +213,31 @@ LINEBLOCK* compilestrconst(char* str) {
|
|||
appendlnbefore(blk, mksimpleln(mknew, strcount(mknew)));
|
||||
appendlnbefore(blk, mksimpleln(strsize, strcount(strsize)));
|
||||
free(strsize[2]);
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
LINEBLOCK* compilearrayitem(SCOPE* s, TERM* t) {
|
||||
LINEBLOCK* blk = compileexpression(s, t->array->exp);
|
||||
appendln(blk, pushvar(s, t->array->name));
|
||||
|
||||
appendln(blk, onetoken("add"));
|
||||
|
||||
appendln(blk, popthatadd());
|
||||
appendln(blk, pushthat());
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
LINEBLOCK* compileterm(SCOPE* s, TERM* t) {
|
||||
if(t->type == intconstant) return pushconstant(t->integer);
|
||||
if(t->type == intconstant) return mklnblk(pushconstant(t->integer));
|
||||
if(t->type == unaryopterm) return pushunaryopterm(s, t);
|
||||
if(t->type == innerexpression) return compileexpression(s, t->expression);
|
||||
if(t->type == varname) return pushvar(s, t->string);
|
||||
if(t->type == varname) return mklnblk(pushvar(s, t->string));
|
||||
if(t->type == subroutcall) return compilesubroutcall(s, t->call);
|
||||
if(t->type == keywordconstant) return compilekeywordconst(s, t);
|
||||
if(t->type == stringconstant) return compilestrconst(t->string);
|
||||
return compilearrayitem(s, t);
|
||||
}
|
||||
|
||||
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
|
||||
|
@ -248,16 +291,15 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
|||
|
||||
if(d->subroutclass == method) {
|
||||
if(call->parentname == NULL)
|
||||
blk = mergelnblks(pushthis(), blk);
|
||||
appendlnbefore(blk, pushthisadd());
|
||||
else
|
||||
blk = mergelnblks(pushvarraw(s, v), blk);
|
||||
appendlnbefore(blk, pushvarraw(s, v));
|
||||
}
|
||||
|
||||
// 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*)));
|
||||
appendln(blk, poptemp());
|
||||
}
|
||||
|
||||
return blk;
|
||||
|
@ -316,7 +358,6 @@ LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) {
|
|||
appendln(blk, mksimpleln(endlabelln, strcount(endlabelln)));
|
||||
}
|
||||
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
@ -351,9 +392,20 @@ LINEBLOCK* compilewhile(COMPILER* c, SCOPE* s, CONDSTATEMENT* w) {
|
|||
}
|
||||
|
||||
LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) {
|
||||
// missing array ind
|
||||
LINEBLOCK* blk = compileexpression(s, l->expression);
|
||||
blk = mergelnblks(blk, popvar(s, l->varname));
|
||||
|
||||
if(l->arrayind != NULL) {
|
||||
appendlnbefore(blk, onetoken("add"));
|
||||
appendlnbefore(blk, pushvar(s, l->varname));
|
||||
blk = mergelnblks(compileexpression(s, l->arrayind), blk);
|
||||
|
||||
appendln(blk, poptemp());
|
||||
appendln(blk, popthatadd());
|
||||
appendln(blk, pushtemp());
|
||||
appendln(blk, popthat());
|
||||
}
|
||||
else
|
||||
appendln(blk, popvar(s, l->varname));
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
|
2
main.c
2
main.c
|
@ -135,6 +135,6 @@ int main(int argc, char* argv[]) {
|
|||
currunit = currunit->next;
|
||||
}
|
||||
|
||||
freeos();
|
||||
//freeos();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -78,11 +78,12 @@ bool isdotjack(char* f, int len) {
|
|||
bool isdir(char* f, int len) {
|
||||
bool readsmt = false;
|
||||
for(int i = len-1; i >= 0; i--) {
|
||||
if(f[i] == '.')
|
||||
if(f[i] == '.') {
|
||||
if(readsmt)
|
||||
return false;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if(f[i] == '/')
|
||||
return 1;
|
||||
readsmt = true;
|
||||
|
|
|
@ -14,7 +14,7 @@ CLASS* addclass(const char* name) {
|
|||
return c;
|
||||
}
|
||||
|
||||
CLASS* adddec(CLASS* c, SUBROUTCLASS subroutclass, char* type, const char* name) {
|
||||
void adddec(CLASS* c, SUBROUTCLASS subroutclass, char* type, const char* name) {
|
||||
SUBROUTDEC* dec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
|
||||
dec->class = c;
|
||||
dec->subroutclass = subroutclass;
|
||||
|
@ -151,5 +151,5 @@ SUBROUTDEC* getossubroutdec(SUBROUTCALL* call) {
|
|||
CLASS* c = getosclass(call->parentname);
|
||||
if(c == NULL)
|
||||
return NULL;
|
||||
getsubroutdecinclass(c, call->name);
|
||||
return getsubroutdecinclass(c, call->name);
|
||||
}
|
||||
|
|
|
@ -99,10 +99,11 @@ TERM* parsecalltermnullified(PARSER* p) {
|
|||
|
||||
TERM* parsearrayterm(PARSER* p) {
|
||||
TERM* t = mkterm(arrayitem);
|
||||
t->string = p->current->token;
|
||||
t->array = (ARRAY*)malloc(sizeof(ARRAY));
|
||||
t->array->name = p->current->token;
|
||||
next(p);
|
||||
checkcontent(p, "[");
|
||||
t->arrayexp = parseexpression(p);
|
||||
t->array->exp = parseexpression(p);
|
||||
checkcontent(p, "]");
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,11 @@ typedef enum {
|
|||
varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm
|
||||
} TERMTYPE;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
struct term* exp;
|
||||
} ARRAY;
|
||||
|
||||
typedef struct term {
|
||||
TERMTYPE type;
|
||||
union {
|
||||
|
@ -127,8 +132,8 @@ typedef struct term {
|
|||
int integer;
|
||||
struct subroutcall* call;
|
||||
struct term* expression;
|
||||
ARRAY* array;
|
||||
};
|
||||
struct term* arrayexp;
|
||||
char op;
|
||||
char unaryop;
|
||||
struct term* next;
|
||||
|
|
Loading…
Reference in New Issue