diff --git a/Makefile b/Makefile index 6340dcc..5b164f7 100644 --- a/Makefile +++ b/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} diff --git a/compiler/compiler-scopes.c b/compiler/compiler-scopes.c index bb44e90..8276f50 100644 --- a/compiler/compiler-scopes.c +++ b/compiler/compiler-scopes.c @@ -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; } } diff --git a/compiler/compiler.c b/compiler/compiler.c index e7673fe..33f3f24 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -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)); - } + 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; } diff --git a/main.c b/main.c index cb2706a..0f80feb 100644 --- a/main.c +++ b/main.c @@ -135,6 +135,6 @@ int main(int argc, char* argv[]) { currunit = currunit->next; } - freeos(); + //freeos(); return 0; } diff --git a/misc/io.c b/misc/io.c index 9788b63..d1d7542 100644 --- a/misc/io.c +++ b/misc/io.c @@ -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; diff --git a/misc/os.c b/misc/os.c index 1092c2e..6985273 100644 --- a/misc/os.c +++ b/misc/os.c @@ -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); } diff --git a/parser/parser-expressions.c b/parser/parser-expressions.c index 55c6be0..bccca79 100644 --- a/parser/parser-expressions.c +++ b/parser/parser-expressions.c @@ -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; } diff --git a/parser/parser-tree.h b/parser/parser-tree.h index edf122d..dba2358 100644 --- a/parser/parser-tree.h +++ b/parser/parser-tree.h @@ -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;