From f1f4f1ef8af70303be1c709a5bfc5efb4fd09ac6 Mon Sep 17 00:00:00 2001 From: Augusto Gunsch Date: Sun, 3 Jan 2021 16:08:54 -0300 Subject: [PATCH] Fix bugs, memory leaks and small fixes --- README.md | 2 +- compiler/compiler-expressions.c | 9 +- compiler/compiler-scopes.c | 40 ++++++--- compiler/compiler-scopes.h | 6 +- compiler/compiler-statements.c | 38 ++++----- compiler/compiler-statements.h | 2 +- compiler/compiler-structure.c | 41 ++++++---- compiler/compiler-structure.h | 2 +- compiler/compiler.c | 10 ++- compiler/compiler.h | 1 + main.c | 13 +-- misc/io.c | 8 +- misc/os.c | 98 ++++++++++++---------- misc/os.h | 8 +- misc/threads.c | 8 +- misc/threads.h | 3 +- parser/parser-expressions.c | 1 + parser/parser-structure.c | 2 +- parser/parser-tree.c | 141 ++++++++++++++++++++++++++++++++ parser/parser-tree.h | 2 + parser/parser.c | 17 +++- parser/parser.h | 4 +- tokenizer/tokenizer.c | 8 ++ tokenizer/tokenizer.h | 2 +- vm/vm-lines.c | 6 ++ vm/vm-lines.h | 1 + 26 files changed, 349 insertions(+), 124 deletions(-) create mode 100644 parser/parser-tree.c diff --git a/README.md b/README.md index 6619283..1b3da79 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # jack-compiler -Jack language compiler, as specified in [nand2tetris project 10](https://www.nand2tetris.org/project10).
+Jack language compiler, as specified in [nand2tetris project 10](https://www.nand2tetris.org/project10) and [project 11](https://www.nand2tetris.org/project11)
diff --git a/compiler/compiler-expressions.c b/compiler/compiler-expressions.c index ef45988..27d4432 100644 --- a/compiler/compiler-expressions.c +++ b/compiler/compiler-expressions.c @@ -207,11 +207,10 @@ LINEBLOCK* compileexpression(SCOPE* s, TERM* e) { if(e != NULL) { while(true) { blk = mergelnblks(blk, compileterm(s, e)); - if(e->next != NULL) { - appendln(blk, mathopln(e->op)); - e = e->next; - } - else break; + if(e->next == NULL) + break; + appendln(blk, mathopln(e->op)); + e = e->next; } } return blk; diff --git a/compiler/compiler-scopes.c b/compiler/compiler-scopes.c index 7d7ed7f..6f22673 100644 --- a/compiler/compiler-scopes.c +++ b/compiler/compiler-scopes.c @@ -27,9 +27,9 @@ SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name); 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 addstaticvar(COMPILER* c, SCOPE* s, CLASSVARDEC* v); +void addstaticvar(SCOPE* s, CLASSVARDEC* v); void addfield(SCOPE* s, CLASSVARDEC* v, int* i); -void addclassvardec(COMPILER* c, SCOPE* s, CLASSVARDEC* v, int* i); +void addclassvardec(SCOPE* s, CLASSVARDEC* v, int* i); void addparameter(SCOPE* s, PARAMETER* p, int* i); // Error messages @@ -67,6 +67,8 @@ void ensurenoduplicate(SCOPE* s, char* name) { SCOPE* mkscope(SCOPE* prev) { SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE)); s->previous = prev; + if(prev != NULL) + s->compiler = prev->compiler; s->localvars = NULL; s->fields = NULL; s->staticvars = NULL; @@ -113,7 +115,7 @@ CLASS* getclass(SCOPE* s, const char* name) { } if(s->previous != NULL) return getclass(s->previous, name); - return getosclass(name); + return getosclass(s->compiler->os, name); } SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name) { @@ -174,7 +176,7 @@ SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call, VAR** varret) { SUBROUTDEC* d; *varret = NULL; if(call->parentname != NULL) { - d = getossubroutdec(call); + d = getossubroutdec(s->compiler->os, call); if(d == NULL) d = getsubroutdecwithparent(s, call, varret); } @@ -232,16 +234,16 @@ void addlocalvar(SCOPE* s, VARDEC* v, int* i) { } } -void addstaticvar(COMPILER* c, SCOPE* s, CLASSVARDEC* v) { +void addstaticvar(SCOPE* s, CLASSVARDEC* v) { STRINGLIST* currname = v->base->names; - pthread_mutex_lock(&(c->staticmutex)); + pthread_mutex_lock(&(s->compiler->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)); + pthread_mutex_unlock(&(s->compiler->staticmutex)); } void addfield(SCOPE* s, CLASSVARDEC* v, int* i) { @@ -253,9 +255,9 @@ void addfield(SCOPE* s, CLASSVARDEC* v, int* i) { } } -void addclassvardec(COMPILER* c, SCOPE* s, CLASSVARDEC* v, int* i) { +void addclassvardec(SCOPE* s, CLASSVARDEC* v, int* i) { if(v->type == stat) - addstaticvar(c, s, v); + addstaticvar(s, v); else { addfield(s, v, i); } @@ -267,10 +269,10 @@ void addparameter(SCOPE* s, PARAMETER* p, int* i) { } // Group adding -void addclassvardecs(COMPILER* c, SCOPE* s, CLASSVARDEC* classvardecs) { +void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs) { int i = 0; while(classvardecs != NULL) { - addclassvardec(c, s, classvardecs, &i); + addclassvardec(s, classvardecs, &i); classvardecs = classvardecs->next; } } @@ -290,3 +292,19 @@ void addparameters(SCOPE* s, bool isformethod, PARAMETER* params) { params = params->next; } } + +void freevars(VAR* v) { + if(v != NULL) { + VAR* next = v->next; + free(v); + freevars(next); + } +} + +void freescope(SCOPE* s) { + freevars(s->fields); + freevars(s->staticvars); + freevars(s->localvars); + freevars(s->parameters); + free(s); +}; diff --git a/compiler/compiler-scopes.h b/compiler/compiler-scopes.h index 2664227..1994f77 100644 --- a/compiler/compiler-scopes.h +++ b/compiler/compiler-scopes.h @@ -21,6 +21,7 @@ typedef struct var { } VAR; typedef struct scope { + struct compiler* compiler; DEBUGINFO* currdebug; CLASS* currclass; @@ -38,7 +39,7 @@ typedef struct scope { struct compiler; // Group adding -void addclassvardecs(struct compiler* c, SCOPE* s, CLASSVARDEC* classvardecs); +void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs); void addlocalvars(SCOPE* s, VARDEC* localvars); void addparameters(SCOPE* s, bool isformethod, PARAMETER* params); @@ -51,4 +52,7 @@ CLASS* getclass(SCOPE* s, const char* name); // Generic getters VAR* getvar(SCOPE* s, const char* name); + +// Freeing +void freescope(SCOPE* s); #endif diff --git a/compiler/compiler-statements.c b/compiler/compiler-statements.c index bb50253..f25adcc 100644 --- a/compiler/compiler-statements.c +++ b/compiler/compiler-statements.c @@ -13,10 +13,10 @@ char* mkcondlabel(char* name, int count); // Handling individual statements LINEBLOCK* compileret(SCOPE* s, TERM* e); -LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st); -LINEBLOCK* compilewhile(COMPILER* c, SCOPE* s, CONDSTATEMENT* w); +LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st); +LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w); LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l); -LINEBLOCK* compilestatement(COMPILER* c, SCOPE* s, STATEMENT* st); +LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st); /* END FORWARD DECLARATIONS */ @@ -55,14 +55,14 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) { return blk; } -LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) { +LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) { LINEBLOCK* blk = compileexpression(s, st->base->expression); - pthread_mutex_lock(&(c->ifmutex)); + pthread_mutex_lock(&(s->compiler->ifmutex)); static int ifcount = 0; int mycount = ifcount; ifcount++; - pthread_mutex_unlock(&(c->ifmutex)); + pthread_mutex_unlock(&(s->compiler->ifmutex)); char* truelabel = mkcondlabel("IF_TRUE", mycount); char* ifgoto[] = { "if-goto", truelabel }; @@ -75,7 +75,7 @@ LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) { char* truelabelln[] = { "label", truelabel }; appendln(blk, mkln(truelabelln)); - blk = mergelnblks(blk, compilestatements(c, s, st->base->statements)); + blk = mergelnblks(blk, compilestatements(s, st->base->statements)); char* endlabel; bool haselse = st->elsestatements != NULL; @@ -89,7 +89,7 @@ LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) { appendln(blk, mkln(falselabelln)); if(haselse) { - blk = mergelnblks(blk, compilestatements(c, s, st->elsestatements)); + blk = mergelnblks(blk, compilestatements(s, st->elsestatements)); char* endlabelln[] = { "label", endlabel }; appendln(blk, mkln(endlabelln)); free(endlabel); @@ -101,14 +101,14 @@ LINEBLOCK* compileif(COMPILER* c, SCOPE* s, IFSTATEMENT* st) { return blk; } -LINEBLOCK* compilewhile(COMPILER* c, SCOPE* s, CONDSTATEMENT* w) { +LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w) { LINEBLOCK* blk = compileexpression(s, w->expression); - pthread_mutex_lock(&(c->whilemutex)); + pthread_mutex_lock(&(s->compiler->whilemutex)); static int whilecount = 0; int mycount = whilecount; whilecount++; - pthread_mutex_unlock(&(c->whilemutex)); + pthread_mutex_unlock(&(s->compiler->whilemutex)); char* explabel = mkcondlabel("WHILE_EXP", mycount); char* explabelln[] = { "label", explabel }; @@ -120,7 +120,7 @@ LINEBLOCK* compilewhile(COMPILER* c, SCOPE* s, CONDSTATEMENT* w) { char* ifgoto[] = { "if-goto", endlabel }; appendln(blk, mkln(ifgoto)); - blk = mergelnblks(blk, compilestatements(c, s, w->statements)); + blk = mergelnblks(blk, compilestatements(s, w->statements)); char* gotoln[] = { "goto", explabel }; appendln(blk, mkln(gotoln)); @@ -152,21 +152,19 @@ LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) { return blk; } -LINEBLOCK* compilestatement(COMPILER* c, SCOPE* s, STATEMENT* st) { +LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st) { s->currdebug = st->debug; if(st->type == dostatement) return compilesubroutcall(s, st->dostatement); if(st->type == returnstatement) return compileret(s, st->retstatement); - if(st->type == ifstatement) return compileif(c, s, st->ifstatement); - if(st->type == whilestatement) return compilewhile(c, s, st->whilestatement); - if(st->type == letstatement) return compilelet(s, st->letstatement); - eprintf("UNSUPPORTED type %i\n", st->type); - exit(1); + if(st->type == ifstatement) return compileif(s, st->ifstatement); + if(st->type == whilestatement) return compilewhile(s, st->whilestatement); + return compilelet(s, st->letstatement); } -LINEBLOCK* compilestatements(COMPILER* c, SCOPE* s, STATEMENT* sts) { +LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) { LINEBLOCK* head = NULL; while(sts != NULL) { - head = mergelnblks(head, compilestatement(c, s, sts)); + head = mergelnblks(head, compilestatement(s, sts)); sts = sts->next; } return head; diff --git a/compiler/compiler-statements.h b/compiler/compiler-statements.h index ab347ec..f71273b 100644 --- a/compiler/compiler-statements.h +++ b/compiler/compiler-statements.h @@ -5,5 +5,5 @@ /* compiler-statements * Single function for compiling statements */ -LINEBLOCK* compilestatements(COMPILER* c, SCOPE* s, STATEMENT* sts); +LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts); #endif diff --git a/compiler/compiler-structure.c b/compiler/compiler-structure.c index 87a9a40..9fa5bb6 100644 --- a/compiler/compiler-structure.c +++ b/compiler/compiler-structure.c @@ -12,10 +12,10 @@ int getobjsize(CLASS* c); LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd); // Compiling methods -LINEBLOCK* compilefunbody(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTBODY* b); -LINEBLOCK* compilefundec(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* f); -LINEBLOCK* compileconstructor(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* con); -LINEBLOCK* compilemethod(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* m); +LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTBODY* b); +LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f); +LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con); +LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m); /* END FORWARD DECLARATIONS */ @@ -64,20 +64,21 @@ LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd) { } // Compiling methods -LINEBLOCK* compilefunbody(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTBODY* b) { +LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTBODY* b) { SCOPE* myscope = mkscope(s); myscope->currclass = cl; if(b->vardecs != NULL) - addlocalvars(s, b->vardecs); - LINEBLOCK* head = compilestatements(c, myscope, b->statements); + addlocalvars(myscope, b->vardecs); + LINEBLOCK* head = compilestatements(myscope, b->statements); + freescope(myscope); return head; } -LINEBLOCK* compilefundec(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* f) { +LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f) { LINE* label = mksubdeclabel(cl, f); if(f->body->statements != NULL) { - LINEBLOCK* body = compilefunbody(c, s, cl, f->body); + LINEBLOCK* body = compilefunbody(s, cl, f->body); appendlnbefore(body, label); return body; } @@ -85,7 +86,7 @@ LINEBLOCK* compilefundec(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* f) { return mklnblk(label); } -LINEBLOCK* compileconstructor(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* con) { +LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con) { LINE* label = mksubdeclabel(cl, con); LINEBLOCK* blk = mklnblk(label); @@ -98,12 +99,12 @@ LINEBLOCK* compileconstructor(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* con) free(size[2]); if(con->body != NULL) - return mergelnblks(blk, compilefunbody(c, s, cl, con->body)); + return mergelnblks(blk, compilefunbody(s, cl, con->body)); else return blk; } -LINEBLOCK* compilemethod(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* m) { +LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m) { LINE* label = mksubdeclabel(cl, m); LINEBLOCK* blk = mklnblk(label); @@ -113,18 +114,22 @@ LINEBLOCK* compilemethod(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* m) { appendln(blk, mkln(poppointer)); if(m->body != NULL) - return mergelnblks(blk, compilefunbody(c, s, cl, m->body)); + return mergelnblks(blk, compilefunbody(s, cl, m->body)); else return blk; } -LINEBLOCK* compilesubroutdec(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* sd) { +LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* cl, SUBROUTDEC* sd) { SCOPE* myscope = mkscope(s); + LINEBLOCK* blk; if(sd->parameters != NULL) addparameters(myscope, sd->subroutclass == method, sd->parameters); if(sd->subroutclass == function) - return compilefundec(c, myscope, cl, sd); - if(sd->subroutclass == constructor) - return compileconstructor(c, myscope, cl, sd); - return compilemethod(c, myscope, cl, sd); + blk = compilefundec(myscope, cl, sd); + else if(sd->subroutclass == constructor) + blk = compileconstructor(myscope, cl, sd); + else + blk = compilemethod(myscope, cl, sd); + freescope(myscope); + return blk; } diff --git a/compiler/compiler-structure.h b/compiler/compiler-structure.h index 36ae94a..c23d921 100644 --- a/compiler/compiler-structure.h +++ b/compiler/compiler-structure.h @@ -5,5 +5,5 @@ /* compiler-structure * Module for dealing with and compiling general program structure. */ -LINEBLOCK* compilesubroutdec(COMPILER* c, SCOPE* s, CLASS* cl, SUBROUTDEC* sd); +LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* cl, SUBROUTDEC* sd); #endif diff --git a/compiler/compiler.c b/compiler/compiler.c index 76a87a2..e8e97d7 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -1,4 +1,5 @@ #include +#include "os.h" #include "compiler-structure.h" #include "compiler.h" @@ -7,24 +8,27 @@ LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { SCOPE* topscope = mkscope(c->globalscope); if(class->vardecs != NULL) - addclassvardecs(c, topscope, class->vardecs); + addclassvardecs(topscope, class->vardecs); if(class->subroutdecs != NULL) topscope->subroutines = class->subroutdecs; LINEBLOCK* output = NULL; SUBROUTDEC* curr = class->subroutdecs; while(curr != NULL) { - output = mergelnblks(output, compilesubroutdec(c, topscope, class, curr)); + output = mergelnblks(output, compilesubroutdec(topscope, class, curr)); curr = curr->next; } + freescope(topscope); return output; } COMPILER* mkcompiler(CLASS* classes) { COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER)); c->globalscope = mkscope(NULL); + c->globalscope->compiler = c; c->globalscope->classes = classes; c->classes = classes; + c->os = mkos(); pthread_mutex_init(&(c->ifmutex), NULL); pthread_mutex_init(&(c->whilemutex), NULL); pthread_mutex_init(&(c->staticmutex), NULL); @@ -36,5 +40,7 @@ void freecompiler(COMPILER* c) { pthread_mutex_destroy(&(c->whilemutex)); pthread_mutex_destroy(&(c->staticmutex)); // to be continued + freeos(c->os); + freescope(c->globalscope); free(c); } diff --git a/compiler/compiler.h b/compiler/compiler.h index 1ecc1e0..3009896 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -15,6 +15,7 @@ typedef struct compiler { pthread_mutex_t whilemutex; pthread_mutex_t staticmutex; CLASS* classes; + CLASS* os; struct scope* globalscope; } COMPILER; diff --git a/main.c b/main.c index 8213f1f..f94a80b 100644 --- a/main.c +++ b/main.c @@ -20,13 +20,13 @@ int main(int argc, char* argv[]) { COMPILEUNIT* head = (COMPILEUNIT*)malloc(sizeof(COMPILEUNIT)); head->file = files; - head->tokens = tokenize(files->fullname); + head->parser = mkparser(tokenize(files->fullname), files->name); COMPILEUNIT* currunit = head; while(curr != NULL) { COMPILEUNIT* newunit = (COMPILEUNIT*)malloc(sizeof(COMPILEUNIT)); newunit->file = curr; - newunit->tokens = tokenize(curr->fullname); + newunit->parser = mkparser(tokenize(curr->fullname), curr->name); currunit->next = newunit; currunit = newunit; curr = curr->next; @@ -52,7 +52,6 @@ int main(int argc, char* argv[]) { currunit = currunit->next; } - populateos(); actonunits(head, compileunit); currunit = head; @@ -64,9 +63,13 @@ int main(int argc, char* argv[]) { } printlns(currunit->compiled->head, output); fclose(output); - currunit = currunit->next; + COMPILEUNIT* next = currunit->next; + freeunit(currunit); + currunit = next; } - //freeos(); + freecompiler(compiler); + freetree(headclass); + freefilelist(files); return 0; } diff --git a/misc/io.c b/misc/io.c index d1d7542..15ea492 100644 --- a/misc/io.c +++ b/misc/io.c @@ -96,6 +96,7 @@ char* getoutname(char* fullname, int len) { int sz = sizeof(char) * (len-1); char* outname = (char*)malloc(sz); sprintf(outname, "%svm", trimmed); + free(trimmed); return outname; } @@ -171,6 +172,9 @@ FILELIST* getfiles(char* input) { void freefilelist(FILELIST* fs) { free(fs->name); free(fs->fullname); - if(fs->next != NULL) - freefilelist(fs->next); + free(fs->outname); + FILELIST* next = fs->next; + free(fs); + if(next != NULL) + freefilelist(next); } diff --git a/misc/os.c b/misc/os.c index 3329548..a91a6d5 100644 --- a/misc/os.c +++ b/misc/os.c @@ -3,14 +3,11 @@ #include "os.h" #include "util.h" -CLASS* classes = NULL; - -CLASS* addclass(const char* name) { +CLASS* mkosclass(CLASS* os, const char* name) { CLASS* c = (CLASS*)malloc(sizeof(CLASS)); c->name = ezheapstr(name); c->subroutdecs = NULL; - c->next = classes; - classes = c; + c->next = os; return c; } @@ -18,24 +15,25 @@ void adddec(CLASS* c, SUBROUTCLASS subroutclass, char* type, const char* name) { SUBROUTDEC* dec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC)); dec->class = c; dec->subroutclass = subroutclass; - dec->type = type; dec->name = ezheapstr(name); + dec->type = ezheapstr(type); dec->next = c->subroutdecs; c->subroutdecs = dec; } -void populatemath() { - CLASS* mathclass = addclass("Math"); +CLASS* mkmath(CLASS* os) { + CLASS* mathclass = mkosclass(os, "Math"); adddec(mathclass, function, "int", "multiply"); adddec(mathclass, function, "int", "divide"); adddec(mathclass, function, "int", "abs"); adddec(mathclass, function, "int", "min"); adddec(mathclass, function, "int", "max"); adddec(mathclass, function, "int", "sqrt"); + return mathclass; } -void populatestringclass() { - CLASS* strclass = addclass("String"); +CLASS* mkstringclass(CLASS* os) { + CLASS* strclass = mkosclass(os, "String"); adddec(strclass, constructor, "String", "new"); adddec(strclass, method, "int", "dispose"); adddec(strclass, method, "int", "length"); @@ -48,84 +46,96 @@ void populatestringclass() { adddec(strclass, function, "char", "backSpace"); adddec(strclass, function, "char", "doubleQuote"); adddec(strclass, function, "char", "newLine"); + return strclass; } -void populatearray() { - CLASS* arrclass = addclass("Array"); +CLASS* mkarray(CLASS* os) { + CLASS* arrclass = mkosclass(os, "Array"); adddec(arrclass, function, "Array", "new"); adddec(arrclass, method, "void", "dispose"); + return arrclass; } -void populateoutput() { - CLASS* outclass = addclass("Output"); +CLASS* mkoutput(CLASS* os) { + CLASS* outclass = mkosclass(os, "Output"); adddec(outclass, function, "void", "moveCursor"); adddec(outclass, function, "void", "printChar"); adddec(outclass, function, "void", "printString"); adddec(outclass, function, "void", "printInt"); adddec(outclass, function, "void", "println"); adddec(outclass, function, "void", "backSpace"); + return outclass; } -void populatescreen() { - CLASS* scrclass = addclass("Screen"); +CLASS* mkscreen(CLASS* os) { + CLASS* scrclass = mkosclass(os, "Screen"); adddec(scrclass, function, "void", "clearScreen"); adddec(scrclass, function, "void", "setColor"); adddec(scrclass, function, "void", "drawPixel"); adddec(scrclass, function, "void", "drawLine"); adddec(scrclass, function, "void", "drawRectangle"); adddec(scrclass, function, "void", "drawCircle"); + return scrclass; } -void populatekeyboard() { - CLASS* kbdclass = addclass("Keyboard"); +CLASS* mkkeyboard(CLASS* os) { + CLASS* kbdclass = mkosclass(os, "Keyboard"); adddec(kbdclass, function, "char", "keyPressed"); adddec(kbdclass, function, "char", "readChar"); adddec(kbdclass, function, "String", "readLine"); adddec(kbdclass, function, "int", "readInt"); + return kbdclass; } -void populatememory() { - CLASS* memclass = addclass("Memory"); +CLASS* mkmemory(CLASS* os) { + CLASS* memclass = mkosclass(os, "Memory"); adddec(memclass, function, "int", "peek"); adddec(memclass, function, "void", "poke"); adddec(memclass, function, "Array", "alloc"); adddec(memclass, function, "void", "deAlloc"); + return memclass; } -void populatesys() { - CLASS* sysclass = addclass("Sys"); +CLASS* mksys(CLASS* os) { + CLASS* sysclass = mkosclass(os, "Sys"); adddec(sysclass, function, "void", "halt"); adddec(sysclass, function, "void", "error"); adddec(sysclass, function, "void", "wait"); + return sysclass; } -void populateos() { - populatemath(); - populatestringclass(); - populatearray(); - populateoutput(); - populatescreen(); - populatekeyboard(); - populatememory(); - populatesys(); +CLASS* mkos() { + CLASS* os = mkmath(NULL); + os = mkstringclass(os); + os = mkarray(os); + os = mkoutput(os); + os = mkscreen(os); + os = mkkeyboard(os); + os = mkmemory(os); + os = mksys(os); + return os; } -void freesubroutdecs(SUBROUTDEC* d) { +void freeossubroutdecs(SUBROUTDEC* d) { free(d->name); free(d->type); - if(d->next != NULL) - freesubroutdecs(d->next); + SUBROUTDEC* next = d->next; + free(d); + if(next != NULL) + freeossubroutdecs(next); } -void freeclasses(CLASS* c) { - freesubroutdecs(c->subroutdecs); +void freeosclasses(CLASS* c) { + freeossubroutdecs(c->subroutdecs); free(c->name); - if(c->next != NULL) - freeclasses(c->next); + CLASS* next = c->next; + free(c); + if(next != NULL) + freeosclasses(next); } -void freeos() { - freeclasses(classes); +void freeos(CLASS* os) { + freeosclasses(os); } SUBROUTDEC* getsubroutdecinclass(CLASS* c, const char* name) { @@ -138,8 +148,8 @@ SUBROUTDEC* getsubroutdecinclass(CLASS* c, const char* name) { return NULL; } -CLASS* getosclass(const char* name) { - CLASS* curr = classes; +CLASS* getosclass(CLASS* os, const char* name) { + CLASS* curr = os; while(curr != NULL) { if(!strcmp(curr->name, name)) return curr; @@ -148,8 +158,8 @@ CLASS* getosclass(const char* name) { return NULL; } -SUBROUTDEC* getossubroutdec(SUBROUTCALL* call) { - CLASS* c = getosclass(call->parentname); +SUBROUTDEC* getossubroutdec(CLASS* os, SUBROUTCALL* call) { + CLASS* c = getosclass(os, call->parentname); if(c == NULL) return NULL; return getsubroutdecinclass(c, call->name); diff --git a/misc/os.h b/misc/os.h index 5ced893..6ca468b 100644 --- a/misc/os.h +++ b/misc/os.h @@ -2,9 +2,9 @@ #define OS_H #include "parser-tree.h" -SUBROUTDEC* getossubroutdec(SUBROUTCALL* call); -CLASS* getosclass(const char* name); -void populateos(); -void freeos(); +SUBROUTDEC* getossubroutdec(CLASS* os, SUBROUTCALL* call); +CLASS* getosclass(CLASS* os, const char* name); +CLASS* mkos(); +void freeos(CLASS* os); #endif diff --git a/misc/threads.c b/misc/threads.c index e34aa69..e9032bf 100644 --- a/misc/threads.c +++ b/misc/threads.c @@ -7,7 +7,7 @@ void* parseunit(void* input) { COMPILEUNIT* unit = (COMPILEUNIT*)input; - unit->parsed = parse(unit->tokens, unit->file->name); + unit->parsed = parse(unit->parser); pthread_exit(NULL); } @@ -60,3 +60,9 @@ void actonunits(COMPILEUNIT* units, void*(*fun)(void*)) { pthread_attr_destroy(&attr); } + +void freeunit(COMPILEUNIT* u) { + freeparser(u->parser); + freelnblk(u->compiled); + free(u); +} diff --git a/misc/threads.h b/misc/threads.h index fbbf106..6305a23 100644 --- a/misc/threads.h +++ b/misc/threads.h @@ -10,7 +10,7 @@ typedef struct unit { FILELIST* file; - TOKEN* tokens; + PARSER* parser; CLASS* parsed; COMPILER* compiler; LINEBLOCK* compiled; @@ -21,4 +21,5 @@ void* parseunit(void* input); void* compileunit(void* input); void waitthreads(pthread_t* threads, int amount); void actonunits(COMPILEUNIT* units, void*(*fun)(void*)); +void freeunit(COMPILEUNIT* u); #endif diff --git a/parser/parser-expressions.c b/parser/parser-expressions.c index aed06dc..019d447 100644 --- a/parser/parser-expressions.c +++ b/parser/parser-expressions.c @@ -166,6 +166,7 @@ TERM* parseexpression(PARSER* p) { } SUBROUTCALL* nullsubroutcall(PARSER* p, SUBROUTCALL* c) { + free(c->debug); free(c); rewindparser(p); return NULL; diff --git a/parser/parser-structure.c b/parser/parser-structure.c index 9cb6e21..f9fad32 100644 --- a/parser/parser-structure.c +++ b/parser/parser-structure.c @@ -167,9 +167,9 @@ SUBROUTDEC* parsesubroutdecs(PARSER* p, CLASS* c) { } PARAMETER* parseparameter(PARSER* p) { - PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER)); if(equals(p, ")")) return NULL; + PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER)); param->debug = getdebug(p); param->primitive = isprimitive(p->current); param->type = parsetype(p); diff --git a/parser/parser-tree.c b/parser/parser-tree.c new file mode 100644 index 0000000..c37c856 --- /dev/null +++ b/parser/parser-tree.c @@ -0,0 +1,141 @@ +#include +#include "parser-tree.h" + +void freeexpression(TERM* e); +void freeexpressionlist(EXPRESSIONLIST* el); +void freestatements(STATEMENT* s); + +void freevardec(VARDEC* v) { + freestrlist(v->names); + free(v->debug); + free(v); +} + +void freevardecs(VARDEC* v) { + VARDEC* next = v->next; + freevardec(v); + if(next != NULL) + freevardecs(next); +} + +void freeparameters(PARAMETER* p) { + free(p->debug); + PARAMETER* next = p->next; + free(p); + if(next != NULL) + freeparameters(next); +} + +void freearray(ARRAY* a) { + freeexpression(a->exp); + free(a); +} + +void freesubroutcall(SUBROUTCALL* call) { + if(call->parameters != NULL) + freeexpressionlist(call->parameters); + free(call->debug); + free(call); +} + +void freeexpression(TERM* e) { + if(e->type == arrayitem) + freearray(e->array); + else if(e->type == innerexpression || e->type == unaryopterm) + freeexpression(e->expression); + else if(e->type == subroutcall) + freesubroutcall(e->call); + TERM* next = e->next; + free(e); + if(next != NULL) + freeexpression(next); +} + +void freeexpressionlist(EXPRESSIONLIST* el) { + freeexpression(el->expression); + EXPRESSIONLIST* next = el->next; + free(el); + if(next != NULL) + freeexpressionlist(next); +} + +void freelet(LETSTATEMENT* l) { + if(l->arrayind != NULL) + freeexpression(l->arrayind); + freeexpression(l->expression); + free(l); +} + +void freecond(CONDSTATEMENT* cond) { + freeexpression(cond->expression); + if(cond->statements != NULL) + freestatements(cond->statements); + free(cond); +} + +void freeif(IFSTATEMENT* st) { + freecond(st->base); + if(st->elsestatements != NULL) + freestatements(st->elsestatements); + free(st); +} + +void freestatements(STATEMENT* s) { + if(s->type == letstatement) + freelet(s->letstatement); + else if(s->type == ifstatement) + freeif(s->ifstatement); + else if(s->type == whilestatement) + freecond(s->whilestatement); + else if(s->type == dostatement) + freesubroutcall(s->dostatement); + else if(s->retstatement != NULL) + freeexpression(s->retstatement); + + free(s->debug); + STATEMENT* next = s->next; + free(s); + if(next != NULL) + freestatements(next); +} + +void freesubroutbody(SUBROUTBODY* b) { + if(b->vardecs != NULL) + freevardecs(b->vardecs); + if(b->statements != NULL) + freestatements(b->statements); + free(b); +} + +void freesubroutdecs(SUBROUTDEC* sr) { + free(sr->debug); + if(sr->parameters != NULL) + freeparameters(sr->parameters); + freesubroutbody(sr->body); + SUBROUTDEC* next = sr->next; + free(sr); + if(next != NULL) + freesubroutdecs(next); +} + +void freeclassvardecs(CLASSVARDEC* cvd) { + freevardec(cvd->base); + CLASSVARDEC* next = cvd->next; + free(cvd); + if(next != NULL) + freeclassvardecs(next); +} + +void freetree(CLASS* c) { + free(c->debug); + + if(c->vardecs != NULL) + freeclassvardecs(c->vardecs); + if(c->subroutdecs != NULL) + freesubroutdecs(c->subroutdecs); + + CLASS* next = c->next; + free(c); + if(next != NULL) + freetree(next); +} diff --git a/parser/parser-tree.h b/parser/parser-tree.h index d423f68..cf2207b 100644 --- a/parser/parser-tree.h +++ b/parser/parser-tree.h @@ -155,4 +155,6 @@ typedef struct expressionlist { struct expressionlist* next; } EXPRESSIONLIST; + +void freetree(CLASS* c); #endif diff --git a/parser/parser.c b/parser/parser.c index 732ccfe..8c82f38 100644 --- a/parser/parser.c +++ b/parser/parser.c @@ -5,10 +5,19 @@ #include "parser.h" #include "parser-structure.h" -CLASS* parse(TOKEN* tokens, char* file) { +PARSER* mkparser(TOKEN* t, char* file) { PARSER* parser = (PARSER*)malloc(sizeof(PARSER)); - parser->tokens = tokens; - parser->current = tokens; + parser->tokens = t; + parser->current = t; parser->file = file; - return parseclass(parser); + return parser; +} + +CLASS* parse(PARSER* p) { + return parseclass(p); +} + +void freeparser(PARSER* p) { + freetokens(p->tokens); + free(p); } diff --git a/parser/parser.h b/parser/parser.h index df54c7f..7a2a2d1 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -14,5 +14,7 @@ typedef struct { char* file; } PARSER; -CLASS* parse(TOKEN* tokens, char* file); +PARSER* mkparser(TOKEN* t, char* file); +CLASS* parse(PARSER* p); +void freeparser(PARSER* p); #endif diff --git a/tokenizer/tokenizer.c b/tokenizer/tokenizer.c index 6831655..9ed303e 100644 --- a/tokenizer/tokenizer.c +++ b/tokenizer/tokenizer.c @@ -78,6 +78,14 @@ TOKEN* appendtokenraw(TOKEN* curitem, STRING* token, int definedat, TOKENTYPE ty return nextitem; } +void freetokens(TOKEN* t) { + free(t->token); + TOKEN* next = t->next; + free(t); + if(next != NULL) + freetokens(next); +} + TOKEN* appendtoken(TOKEN* curitem, STRING* token, char* file, int definedat) { append(token, '\0'); return appendtokenraw(curitem, token, definedat, gettokentype(token, file, definedat)); diff --git a/tokenizer/tokenizer.h b/tokenizer/tokenizer.h index d3b47c6..2d2a5f6 100644 --- a/tokenizer/tokenizer.h +++ b/tokenizer/tokenizer.h @@ -17,5 +17,5 @@ typedef struct token { } TOKEN; TOKEN* tokenize(char* filename); -void freetokenlist(TOKEN* list); +void freetokens(TOKEN* t); #endif diff --git a/vm/vm-lines.c b/vm/vm-lines.c index 6a0bf9f..69541f7 100644 --- a/vm/vm-lines.c +++ b/vm/vm-lines.c @@ -32,6 +32,7 @@ void printlns(LINE* lns, FILE* stream) { void freeln(LINE* ln) { for(int i = 0; i < ln->count; i++) free(ln->tokens[i]); + free(ln->tokens); free(ln); } @@ -42,6 +43,11 @@ void freelns(LINE* lns) { freelns(next); } +void freelnblk(LINEBLOCK* blk) { + freelns(blk->head); + free(blk); +} + LINEBLOCK* mklnblk(LINE* start) { LINEBLOCK* blk = (LINEBLOCK*)malloc(sizeof(LINEBLOCK)); blk->head = start; diff --git a/vm/vm-lines.h b/vm/vm-lines.h index 186d414..9503c10 100644 --- a/vm/vm-lines.h +++ b/vm/vm-lines.h @@ -29,6 +29,7 @@ void printlns(LINE* lns, FILE* stream); // Line freeing void freeln(LINE* ln); void freelns(LINE* lns); +void freelnblk(LINEBLOCK* blk); // Line block manipulation LINEBLOCK* mklnblk(LINE* start);