Add array accessing

This commit is contained in:
Augusto Gunsch 2020-12-31 16:49:38 -03:00
parent 2e86c2b9e5
commit b9a553b107
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
8 changed files with 114 additions and 56 deletions

View File

@ -1,7 +1,7 @@
FILES = *.c */*.c FILES = *.c */*.c
LIBRARIES = -lpthread LIBRARIES = -lpthread
INCLUDES = -I. -I./parser/ -I./compiler/ -I./vm/ -I./tokenizer/ -I./misc/ INCLUDES = -I. -I./parser/ -I./compiler/ -I./vm/ -I./tokenizer/ -I./misc/
CFLAGS = -std=c99 -g CFLAGS = -std=c99 -g -Wall
OUTFILE = jack-compiler OUTFILE = jack-compiler
main: ${FILES} main: ${FILES}

View File

@ -26,11 +26,11 @@ SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
// Scope adding // Scope adding
VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg, int i); VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg, int i);
void addvar(SCOPE* s, VAR** dest, VAR* v); 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 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 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 // Error messages
void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2) { void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2) {
@ -223,32 +223,33 @@ void addvar(SCOPE* s, VAR** dest, VAR* v) {
*dest = v; *dest = v;
} }
void addlocalvar(SCOPE* s, VARDEC* v, int i) { void addlocalvar(SCOPE* s, VARDEC* v, int* i) {
STRINGLIST* currname = v->names; STRINGLIST* currname = v->names;
while(currname != NULL) { 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; currname = currname->next;
(*i)++;
} }
} }
void addstaticvar(COMPILER* c, SCOPE* s, CLASSVARDEC* v) { 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; STRINGLIST* currname = v->base->names;
pthread_mutex_lock(&(c->staticmutex));
static int i = 0;
while(currname != NULL) { while(currname != NULL) {
addvar(s, &(s->staticvars), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, staticseg, i)); addvar(s, &(s->staticvars), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, staticseg, i));
currname = currname->next; 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; STRINGLIST* currname = v->base->names;
while(currname != NULL) { 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; currname = currname->next;
(*i)++;
} }
} }
@ -256,13 +257,13 @@ void addclassvardec(COMPILER* c, SCOPE* s, CLASSVARDEC* v, int* i) {
if(v->type == stat) if(v->type == stat)
addstaticvar(c, s, v); addstaticvar(c, s, v);
else { else {
addfield(s, v, *i); addfield(s, v, i);
*i++;
} }
} }
void addparameter(SCOPE* s, PARAMETER* p, int i) { void addparameter(SCOPE* s, PARAMETER* p, int* i) {
addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg, i)); addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg, *i));
(*i)++;
} }
// Group adding // Group adding
@ -277,8 +278,7 @@ void addclassvardecs(COMPILER* c, SCOPE* s, CLASSVARDEC* classvardecs) {
void addlocalvars(SCOPE* s, VARDEC* localvars) { void addlocalvars(SCOPE* s, VARDEC* localvars) {
int i = 0; int i = 0;
while(localvars != NULL) { while(localvars != NULL) {
addlocalvar(s, localvars, i); addlocalvar(s, localvars, &i);
i++;
localvars = localvars->next; localvars = localvars->next;
} }
} }
@ -286,8 +286,7 @@ void addlocalvars(SCOPE* s, VARDEC* localvars) {
void addparameters(SCOPE* s, PARAMETER* params) { void addparameters(SCOPE* s, PARAMETER* params) {
int i = 0; int i = 0;
while(params != NULL) { while(params != NULL) {
addparameter(s, params, i); addparameter(s, params, &i);
i++;
params = params->next; params = params->next;
} }
} }

View File

@ -85,15 +85,13 @@ LINE* mathopln(char op) {
char* tokens[] = { "call", "Math.divide", "2" }; char* tokens[] = { "call", "Math.divide", "2" };
return mksimpleln(tokens, strcount(tokens)); return mksimpleln(tokens, strcount(tokens));
} }
if(op == '*') { char* tokens[] = { "call", "Math.multiply", "2" };
char* tokens[] = { "call", "Math.multiply", "2" }; return mksimpleln(tokens, strcount(tokens));
return mksimpleln(tokens, strcount(tokens));
}
} }
LINEBLOCK* pushconstant(int n) { LINE* pushconstant(int n) {
char* tokens[] = { "push", "constant", itoa(n) }; char* tokens[] = { "push", "constant", itoa(n) };
return mklnblk(mksimpleln(tokens, strcount(tokens))); return mksimpleln(tokens, strcount(tokens));
} }
LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) { LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
@ -107,47 +105,77 @@ LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
return blk; 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) }; 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); VAR* v = getvar(s, name);
return opvarraw(s, op, v); return opvarraw(s, op, v);
} }
LINEBLOCK* pushvarraw(SCOPE*s, VAR* v) { LINE* pushvarraw(SCOPE*s, VAR* v) {
return opvarraw(s, "push", 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); return opvar(s, "push", name);
} }
LINEBLOCK* popvar(SCOPE* s, const char* name) { LINE* popvar(SCOPE* s, const char* name) {
return opvar(s, "pop", name); return opvar(s, "pop", name);
} }
LINEBLOCK* pushfalse() { LINE* pushfalse() {
return pushconstant(0); return pushconstant(0);
} }
LINEBLOCK* pushtrue() { LINEBLOCK* pushtrue() {
LINEBLOCK* blk = pushfalse(); LINEBLOCK* blk = mklnblk(pushfalse());
appendln(blk, onetoken("not")); appendln(blk, onetoken("not"));
return blk; return blk;
} }
LINEBLOCK* pushthis() { LINE* pushthisadd() {
char* pushthis[] = { "push", "pointer", "0" }; char* pushthisadd[] = { "push", "pointer", "0" };
return mklnblk(mksimpleln(pushthis, strcount(pushthis))); 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) { 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 mklnblk(pushfalse());
if(!strcmp(t->string, "this")) return pushthis(); if(!strcmp(t->string, "this")) return mklnblk(pushthisadd());
eprintf("Unsupported keyword '%s'\n", t->string); eprintf("Unsupported keyword '%s'\n", t->string);
exit(1); exit(1);
} }
@ -185,16 +213,31 @@ LINEBLOCK* compilestrconst(char* str) {
appendlnbefore(blk, mksimpleln(mknew, strcount(mknew))); appendlnbefore(blk, mksimpleln(mknew, strcount(mknew)));
appendlnbefore(blk, mksimpleln(strsize, strcount(strsize))); appendlnbefore(blk, mksimpleln(strsize, strcount(strsize)));
free(strsize[2]); 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) { 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 == unaryopterm) return pushunaryopterm(s, t);
if(t->type == innerexpression) return compileexpression(s, t->expression); 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 == subroutcall) return compilesubroutcall(s, t->call);
if(t->type == keywordconstant) return compilekeywordconst(s, t); if(t->type == keywordconstant) return compilekeywordconst(s, t);
if(t->type == stringconstant) return compilestrconst(t->string); if(t->type == stringconstant) return compilestrconst(t->string);
return compilearrayitem(s, t);
} }
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) { LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
@ -248,16 +291,15 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
if(d->subroutclass == method) { if(d->subroutclass == method) {
if(call->parentname == NULL) if(call->parentname == NULL)
blk = mergelnblks(pushthis(), blk); appendlnbefore(blk, pushthisadd());
else else
blk = mergelnblks(pushvarraw(s, v), blk); appendlnbefore(blk, pushvarraw(s, v));
} }
// void functions always return 0 // void functions always return 0
// therefore must be thrown away // therefore must be thrown away
if(!strcmp(d->type, "void")) { if(!strcmp(d->type, "void")) {
char* tokens[] = { "pop", "temp", "0" }; appendln(blk, poptemp());
appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
} }
return blk; return blk;
@ -316,7 +358,6 @@ LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) {
appendln(blk, mksimpleln(endlabelln, strcount(endlabelln))); appendln(blk, mksimpleln(endlabelln, strcount(endlabelln)));
} }
return blk; return blk;
} }
@ -351,9 +392,20 @@ LINEBLOCK* compilewhile(COMPILER* c, SCOPE* s, CONDSTATEMENT* w) {
} }
LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) { LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) {
// missing array ind
LINEBLOCK* blk = compileexpression(s, l->expression); 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; return blk;
} }

2
main.c
View File

@ -135,6 +135,6 @@ int main(int argc, char* argv[]) {
currunit = currunit->next; currunit = currunit->next;
} }
freeos(); //freeos();
return 0; return 0;
} }

View File

@ -78,11 +78,12 @@ bool isdotjack(char* f, int len) {
bool isdir(char* f, int len) { bool isdir(char* f, int len) {
bool readsmt = false; bool readsmt = false;
for(int i = len-1; i >= 0; i--) { for(int i = len-1; i >= 0; i--) {
if(f[i] == '.') if(f[i] == '.') {
if(readsmt) if(readsmt)
return false; return false;
else else
continue; continue;
}
if(f[i] == '/') if(f[i] == '/')
return 1; return 1;
readsmt = true; readsmt = true;

View File

@ -14,7 +14,7 @@ CLASS* addclass(const char* name) {
return c; 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)); SUBROUTDEC* dec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
dec->class = c; dec->class = c;
dec->subroutclass = subroutclass; dec->subroutclass = subroutclass;
@ -151,5 +151,5 @@ SUBROUTDEC* getossubroutdec(SUBROUTCALL* call) {
CLASS* c = getosclass(call->parentname); CLASS* c = getosclass(call->parentname);
if(c == NULL) if(c == NULL)
return NULL; return NULL;
getsubroutdecinclass(c, call->name); return getsubroutdecinclass(c, call->name);
} }

View File

@ -99,10 +99,11 @@ TERM* parsecalltermnullified(PARSER* p) {
TERM* parsearrayterm(PARSER* p) { TERM* parsearrayterm(PARSER* p) {
TERM* t = mkterm(arrayitem); TERM* t = mkterm(arrayitem);
t->string = p->current->token; t->array = (ARRAY*)malloc(sizeof(ARRAY));
t->array->name = p->current->token;
next(p); next(p);
checkcontent(p, "["); checkcontent(p, "[");
t->arrayexp = parseexpression(p); t->array->exp = parseexpression(p);
checkcontent(p, "]"); checkcontent(p, "]");
return t; return t;
} }

View File

@ -120,6 +120,11 @@ typedef enum {
varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm
} TERMTYPE; } TERMTYPE;
typedef struct {
char* name;
struct term* exp;
} ARRAY;
typedef struct term { typedef struct term {
TERMTYPE type; TERMTYPE type;
union { union {
@ -127,8 +132,8 @@ typedef struct term {
int integer; int integer;
struct subroutcall* call; struct subroutcall* call;
struct term* expression; struct term* expression;
ARRAY* array;
}; };
struct term* arrayexp;
char op; char op;
char unaryop; char unaryop;
struct term* next; struct term* next;