From a1c8c817c84cbd29fa27b894d3ba813353720e8a Mon Sep 17 00:00:00 2001 From: Augusto Gunsch Date: Thu, 31 Dec 2020 13:07:26 -0300 Subject: [PATCH] Add operating system subroutine signatures --- compiler/compiler-scopes.c | 42 ++++++---- compiler/compiler-scopes.h | 2 +- compiler/compiler.c | 72 +++++++---------- main.c | 3 + os.c | 159 +++++++++++++++++++++++++++++++++++++ os.h | 9 +++ parser/parser-structure.c | 16 ++-- parser/parser-tree.h | 1 + 8 files changed, 237 insertions(+), 67 deletions(-) create mode 100644 os.c create mode 100644 os.h diff --git a/compiler/compiler-scopes.c b/compiler/compiler-scopes.c index 9840de3..0866af6 100644 --- a/compiler/compiler-scopes.c +++ b/compiler/compiler-scopes.c @@ -2,6 +2,7 @@ #include #include #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); diff --git a/compiler/compiler-scopes.h b/compiler/compiler-scopes.h index c72f4ec..fbf7703 100644 --- a/compiler/compiler-scopes.h +++ b/compiler/compiler-scopes.h @@ -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 diff --git a/compiler/compiler.c b/compiler/compiler.c index 5bc82c8..d9ae45a 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -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))); diff --git a/main.c b/main.c index 454b513..cb2706a 100644 --- a/main.c +++ b/main.c @@ -7,6 +7,7 @@ #include "parser.h" #include "compiler.h" #include "io.h" +#include "os.h" typedef struct unit { FILELIST* file; @@ -119,6 +120,7 @@ int main(int argc, char* argv[]) { currunit = currunit->next; } + populateos(); actonunits(head, compileunit); currunit = head; @@ -133,5 +135,6 @@ int main(int argc, char* argv[]) { currunit = currunit->next; } + freeos(); return 0; } diff --git a/os.c b/os.c new file mode 100644 index 0000000..9c3365d --- /dev/null +++ b/os.c @@ -0,0 +1,159 @@ +#include +#include +#include "os.h" +#include "util.h" + +#define MATH_COUNT 5 +SUBROUTDEC* math[MATH_COUNT]; +#define STRING_COUNT 12 +SUBROUTDEC* stringclass[STRING_COUNT]; +#define ARRAY_COUNT 2 +SUBROUTDEC* array[ARRAY_COUNT]; +#define OUTPUT_COUNT 6 +SUBROUTDEC* output[OUTPUT_COUNT]; +#define SCREEN_COUNT 6 +SUBROUTDEC* screen[SCREEN_COUNT]; +#define KEYBOARD_COUNT 4 +SUBROUTDEC* keyboard[KEYBOARD_COUNT]; +#define MEMORY_COUNT 4 +SUBROUTDEC* memory[MEMORY_COUNT]; +#define SYS_COUNT 3 +SUBROUTDEC* sys[SYS_COUNT]; + +CLASS* mkclass(const char* name) { + CLASS* class = (CLASS*)malloc(sizeof(CLASS)); + class->name = ezheapstr(name); + return class; +} + +SUBROUTDEC* mkdec(const char* class, SUBROUTCLASS subroutclass, char* type, const char* name) { + SUBROUTDEC* dec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC)); + dec->class = mkclass(class); + dec->subroutclass = subroutclass; + dec->type = type; + dec->name = ezheapstr(name); + return dec; +} + +void populatemath() { + math[0] = mkdec("Math", function, "int", "multiply"); + math[1] = mkdec("Math", function, "int", "divide"); + math[2] = mkdec("Math", function, "int", "min"); + math[3] = mkdec("Math", function, "int", "max"); + math[4] = mkdec("Math", function, "int", "sqrt"); +} + +void populatestringclass() { + stringclass[0] = mkdec("String", constructor, "String", "new"); + stringclass[1] = mkdec("String", method, "int", "dispose"); + stringclass[2] = mkdec("String", method, "int", "length"); + stringclass[3] = mkdec("String", method, "char", "charAt"); + stringclass[4] = mkdec("String", method, "void", "setCharAt"); + stringclass[5] = mkdec("String", method, "String", "appendChar"); + stringclass[6] = mkdec("String", method, "void", "eraseLastChar"); + stringclass[7] = mkdec("String", method, "int", "intValue"); + stringclass[8] = mkdec("String", method, "void", "setInt"); + stringclass[9] = mkdec("String", function, "char", "backSpace"); + stringclass[10] = mkdec("String", function, "char", "doubleQuote"); + stringclass[11] = mkdec("String", function, "char", "newLine"); +} + +void populatearray() { + array[0] = mkdec("Array", function, "Array", "new"); + array[1] = mkdec("Array", method, "void", "dispose"); +} + +void populateoutput() { + output[0] = mkdec("Output", function, "void", "moveCursor"); + output[1] = mkdec("Output", function, "void", "printChar"); + output[2] = mkdec("Output", function, "void", "printString"); + output[3] = mkdec("Output", function, "void", "printInt"); + output[4] = mkdec("Output", function, "void", "printLn"); + output[5] = mkdec("Output", function, "void", "backSpace"); +} + +void populatescreen() { + screen[0] = mkdec("Screen", function, "void", "clearScreen"); + screen[1] = mkdec("Screen", function, "void", "setColor"); + screen[2] = mkdec("Screen", function, "void", "drawPixel"); + screen[3] = mkdec("Screen", function, "void", "drawLine"); + screen[4] = mkdec("Screen", function, "void", "drawRectangle"); + screen[5] = mkdec("Screen", function, "void", "drawCircle"); +} + +void populatekeyboard() { + keyboard[0] = mkdec("Keyboard", function, "char", "keyPressed"); + keyboard[1] = mkdec("Keyboard", function, "char", "readChar"); + keyboard[2] = mkdec("Keyboard", function, "String", "readLine"); + keyboard[3] = mkdec("Keyboard", function, "int", "readInt"); +} + +void populatememory() { + memory[0] = mkdec("Memory", function, "int", "peek"); + memory[1] = mkdec("Memory", function, "void", "poke"); + memory[2] = mkdec("Memory", function, "Array", "alloc"); + memory[3] = mkdec("Memory", function, "void", "deAlloc"); +} + +void populatesys() { + sys[0] = mkdec("Sys", function, "void", "halt"); + sys[1] = mkdec("Sys", function, "void", "error"); + sys[2] = mkdec("Sys", function, "void", "wait"); +} + +void populateos() { + populatemath(); + populatestringclass(); + populatearray(); + populateoutput(); + populatescreen(); + populatekeyboard(); + populatememory(); + populatesys(); +} + +void freedecs(SUBROUTDEC** array, int size) { + for(int i = 0; i < size; i++) { + free(array[i]->class->name); + free(array[i]->class); + free(array[i]->name); + free(array[i]); + } +} + +void freeos() { + freedecs(math, MATH_COUNT); + freedecs(stringclass, STRING_COUNT); + freedecs(array, ARRAY_COUNT); + freedecs(output, OUTPUT_COUNT); + freedecs(screen, SCREEN_COUNT); + freedecs(keyboard, KEYBOARD_COUNT); + freedecs(memory, MEMORY_COUNT); + freedecs(sys, SYS_COUNT); +} + +SUBROUTDEC* getdec(SUBROUTDEC** array, int size, const char* name) { + for(int i = 0; i < size; i++) + if(!strcmp(array[i]->name, name)) + return array[i]; +} + +SUBROUTDEC* getossubroutdec(SUBROUTCALL* call) { + if(!strcmp(call->parentname, "Math")) + return getdec(math, MATH_COUNT, call->name); + if(!strcmp(call->parentname, "String")) + return getdec(stringclass, STRING_COUNT, call->name); + if(!strcmp(call->parentname, "Array")) + return getdec(array, ARRAY_COUNT, call->name); + if(!strcmp(call->parentname, "Output")) + return getdec(output, OUTPUT_COUNT, call->name); + if(!strcmp(call->parentname, "Screen")) + return getdec(screen, SCREEN_COUNT, call->name); + if(!strcmp(call->parentname, "Keyboard")) + return getdec(keyboard, KEYBOARD_COUNT, call->name); + if(!strcmp(call->parentname, "Memory")) + return getdec(memory, MEMORY_COUNT, call->name); + if(!strcmp(call->parentname, "Sys")) + return getdec(sys, SYS_COUNT, call->name); + return NULL; +} diff --git a/os.h b/os.h new file mode 100644 index 0000000..9482db4 --- /dev/null +++ b/os.h @@ -0,0 +1,9 @@ +#ifndef OS_H +#define OS_H +#include "parser-tree.h" + +SUBROUTDEC* getossubroutdec(SUBROUTCALL* call); +void populateos(); +void freeos(); + +#endif diff --git a/parser/parser-structure.c b/parser/parser-structure.c index 08ba8bf..55e9bd8 100644 --- a/parser/parser-structure.c +++ b/parser/parser-structure.c @@ -9,8 +9,8 @@ CLASSVARTYPE parseclassvartype(PARSER* p); CLASSVARDEC* parseclassvardec(PARSER* p); CLASSVARDEC* parseclassvardecs(PARSER* p); SUBROUTCLASS parsesubroutclass(PARSER* p); -SUBROUTDEC* parsesubroutdec(PARSER* p); -SUBROUTDEC* parsesubroutdecs(PARSER* p); +SUBROUTDEC* parsesubroutdec(PARSER* p, CLASS* c); +SUBROUTDEC* parsesubroutdecs(PARSER* p, CLASS* c); PARAMETER* parseparameter(PARSER* p); PARAMETER* parseparameters(PARSER* p); SUBROUTBODY* parsesubroutbody(PARSER* p); @@ -40,7 +40,7 @@ CLASS* parseclass(PARSER* p) { class->vardecs = parseclassvardecs(p); - class->subroutdecs = parsesubroutdecs(p); + class->subroutdecs = parsesubroutdecs(p, class); checkcontent(p, "}"); @@ -94,7 +94,7 @@ SUBROUTCLASS parsesubroutclass(PARSER* p) { return parsepossibilities(p, &subroutclasses); } -SUBROUTDEC* parsesubroutdec(PARSER* p) { +SUBROUTDEC* parsesubroutdec(PARSER* p, CLASS* c) { SUBROUTCLASS subroutclass = parsesubroutclass(p); if(subroutclass == -1) return NULL; @@ -122,14 +122,16 @@ SUBROUTDEC* parsesubroutdec(PARSER* p) { subroutdec->body = parsesubroutbody(p); checkcontent(p, "}"); + subroutdec->class = c; + return subroutdec; } -SUBROUTDEC* parsesubroutdecs(PARSER* p) { - SUBROUTDEC* head = parsesubroutdec(p); +SUBROUTDEC* parsesubroutdecs(PARSER* p, CLASS* c) { + SUBROUTDEC* head = parsesubroutdec(p, c); SUBROUTDEC* curr = head; SUBROUTDEC* nexts; - while(nexts = parsesubroutdec(p), nexts != NULL) { + while(nexts = parsesubroutdec(p, c), nexts != NULL) { curr->next = nexts; curr = nexts; } diff --git a/parser/parser-tree.h b/parser/parser-tree.h index ec80b35..edf122d 100644 --- a/parser/parser-tree.h +++ b/parser/parser-tree.h @@ -49,6 +49,7 @@ typedef enum { typedef struct subroutdec { SUBROUTCLASS subroutclass; + CLASS* class; char* type; char* name; struct parameter* parameters;