Clean compiler-scopes.c

This commit is contained in:
Augusto Gunsch 2020-12-24 16:22:22 -03:00
parent 2e48e42368
commit 6578c9d7eb
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
8 changed files with 144 additions and 250 deletions

View File

@ -3,25 +3,13 @@
#include <string.h> #include <string.h>
#include "compiler-scopes.h" #include "compiler-scopes.h"
// INTERNAL FUNCTIONS
// Information gathering
bool existstr(STRINGLIST* strs, const char* str);
bool existclass(CLASS* c, const char* name);
DEBUGINFO* getdebuginfo(OBJ* obj);
// Error messages // Error messages
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other); void doubledeclaration(const char* name, OBJ* o1, OBJ* o2);
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug); void ensurenoduplicate(SCOPE* s, OBJ* o);
// Scope handling
void popscope(SCOPE** s); // may be removed
// Single type getters
VARDEC* getvardec(SCOPE* s, const char* name);
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name);
// Generic getters // Generic getters
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname); OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname);
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type);
// Scope adding // Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v); void addclassvardec(SCOPE* s, CLASSVARDEC* v);
@ -29,58 +17,20 @@ void addvardec(SCOPE* s, VARDEC* v);
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd); void addsubroutdec(SCOPE* s, SUBROUTDEC* sd);
void addclass(SCOPE* s, CLASS* c); void addclass(SCOPE* s, CLASS* c);
// DEFINITIONS
// Information gathering
bool existstr(STRINGLIST* strs, const char* str) {
while(strs != NULL) {
if(!strcmp(strs->content, str))
return true;
strs = strs->next;
}
return false;
}
bool existclass(CLASS* c, const char* name) {
while(c != NULL) {
if(!strcmp(c->name, name))
return true;
c = c->next;
}
return false;
}
// OBJ handling // OBJ handling
DEBUGINFO* getdebugclassvardec(OBJ* obj) {
return obj->classvardec->base->debug;
}
DEBUGINFO* getdebugvardec(OBJ* obj) {
return obj->vardec->debug;
}
DEBUGINFO* getdebugsubroutdec(OBJ* obj) {
return obj->subroutdec->debug;
}
DEBUGINFO* getdebugclass(OBJ* obj) {
return obj->class->debug;
}
VARDEC* tovardec(OBJ* obj) { VARDEC* tovardec(OBJ* obj) {
if (obj->type == classvardec) if (obj->type == classvardec)
return obj->classvardec->base; return ((CLASSVARDEC*)(obj->pointer))->base;
else if (obj->type == vardec) else if (obj->type == vardec)
return obj->vardec; return (VARDEC*)(obj->pointer);
return NULL; return NULL;
} }
// Error messages // Error messages
void doubledeclaration(const char* name, OBJ* o1, OBJ* o2) {
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other) {
DEBUGINFO* debugother = other->getdebug(other);
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n", eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
name, debug->file, debug->definedat, debugother->file, debugother->definedat); name, o1->debug->file, o1->debug->definedat, o2->debug->file, o2->debug->definedat);
exit(1); exit(1);
} }
@ -94,85 +44,30 @@ void invalidparent(SUBROUTCALL* call) {
exit(1); exit(1);
} }
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug) { void ensurenoduplicate(SCOPE* s, OBJ* o) {
OBJ* other = getbyname(s, name);
if(other != NULL)
doubledeclaration(name, debug, other);
}
void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) {
const char* othername; const char* othername;
OBJ* other = getbynamelist(s, names, &othername); OBJ* other = getbynamelist(s, o->names, &othername);
if(other != NULL) if(other != NULL)
doubledeclaration(othername, debug, other); doubledeclaration(othername, o, other);
} }
// Scope handling // Scope handling
SCOPE* mkscope(SCOPE* prev) { SCOPE* mkscope(SCOPE* prev) {
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE)); SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
s->subroutines = NULL; s->objects = NULL;
s->classvardecs = NULL;
s->vardecs = NULL;
s->classes = NULL;
s->previous = prev; s->previous = prev;
s->condlabelcount = 0; s->condlabelcount = 0;
return s; return s;
} }
void popscope(SCOPE** s) { // might be useless
SCOPE* prev = (*s)->previous;
free(*s);
(*s) = prev;
}
// Single type getters // Single type getters
VARDEC* getvardec(SCOPE* s, const char* name) {
VARDEC* curr = s->vardecs;
while(curr != NULL) {
if(existstr(curr->names, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getvardec(s->previous, name);
return NULL;
}
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name) {
CLASSVARDEC* curr = s->classvardecs;
while(curr != NULL) {
if(existstr(curr->base->names, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getclassvardec(s->previous, name);
return NULL;
}
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) { SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
SUBROUTDEC* curr = s->subroutines; return (SUBROUTDEC*)(getbynamewithtype(s, name, subroutdec)->pointer);
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getsubroutdec(s->previous, name);
return NULL;
} }
CLASS* getclass(SCOPE* s, const char* name) { CLASS* getclass(SCOPE* s, const char* name) {
CLASS* curr = s->classes; return (CLASS*)(getbynamewithtype(s, name, class)->pointer);
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getclass(s->previous, name);
return NULL;
} }
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) { SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) {
@ -201,7 +96,7 @@ SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) {
notdeclared(call->parentname, call->debug); notdeclared(call->parentname, call->debug);
if(parent->type == class) if(parent->type == class)
sd = getsubroutdecfromclass(parent->class, call->name); sd = getsubroutdecfromclass(parent->pointer, call->name);
else else
sd = getsubroutdecfromvar(s, parent, call); sd = getsubroutdecfromvar(s, parent, call);
return sd; return sd;
@ -219,121 +114,88 @@ SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
} }
// Generic getters // Generic getters
OBJ* getbyname(SCOPE* s, const char* name) {
OBJ* o = (OBJ*)malloc(sizeof(OBJ));
CLASSVARDEC* cvd = getclassvardec(s, name);
if(cvd != NULL) {
o->classvardec = cvd;
o->type = classvardec;
o->getdebug = getdebugvardec;
return o;
}
VARDEC* vd = getvardec(s, name);
if(vd != NULL) {
o->vardec = vd;
o->type = vardec;
o->getdebug = getdebugsubroutdec;
return o;
}
SUBROUTDEC* sd = getsubroutdec(s, name);
if(sd != NULL) {
o->subroutdec = sd;
o->type = subroutdec;
o->getdebug = getdebugclassvardec;
return o;
}
CLASS* c = getclass(s, name);
if(c != NULL) {
o->class = c;
o->type = class;
o->getdebug = getdebugclass;
return o;
}
free(o);
return NULL;
}
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) { OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) {
while(names != NULL) { OBJ* curr = s->objects;
OBJ* o = getbyname(s, names->content); while(curr != NULL) {
if(o != NULL) { STRINGLIST* currn = curr->names;
*retname = names->content; while(currn != NULL) {
return o; STRINGLIST* currattempt = names;
while(currattempt != NULL) {
if(!strcmp(currn->content, currattempt->content)) {
*retname = currn->content;
return curr;
}
currattempt = currattempt->next;
}
currn = currn->next;
} }
names = names->next; curr = curr->next;
} }
if(s->previous != NULL) if(s->previous != NULL)
return getbynamelist(s->previous, names, retname); return getbynamelist(s->previous, names, retname);
return NULL; return NULL;
} }
OBJ* getbyname(SCOPE* s, const char* name) {
STRINGLIST* onename = onestr(name);
const char* dummy;
return getbynamelist(s, onename, &dummy);
}
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type) {
OBJ* o = getbyname(s, name);
if(o->type != type)
notdeclared(name, o->debug);
return o;
}
// Scope adding // Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v) { void addobj(SCOPE* s, OBJ* o) {
ensurenoduplicates(s, v->base->names, v->base->debug); ensurenoduplicate(s, o);
CLASSVARDEC* new = copy(v, sizeof(CLASSVARDEC)); o->next = s->objects;
new->next = s->classvardecs; s->objects = o;
s->classvardecs = new;
} }
void addvardec(SCOPE* s, VARDEC* v) { OBJ* mkobj(void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) {
ensurenoduplicates(s, v->names, v->debug); OBJ* o = (OBJ*)malloc(sizeof(OBJ));
VARDEC* new = copy(v, sizeof(VARDEC)); o->pointer = pointer;
new->next = s->vardecs; o->type = type;
s->vardecs = new; o->debug = debug;
o->names = names;
return o;
} }
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd) { void addany(SCOPE* s, void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) {
ensurenoduplicate(s, sd->name, sd->debug); addobj(s, mkobj(pointer, type, debug, names));
SUBROUTDEC* new = copy(sd, sizeof(SUBROUTDEC));
new->next = s->subroutines;
s->subroutines = new;
} }
void addclass(SCOPE* s, CLASS* c) { void addclassvardecs(SCOPE* s, CLASSVARDEC* v) {
ensurenoduplicate(s, c->name, c->debug); addany(s, v, classvardec, v->base->debug, v->base->names);
CLASS* new = copy(c, sizeof(CLASS)); if(v->next != NULL)
new->next = s->classes; addclassvardecs(s, v->next);
s->classes = new;
} }
// Group adding void addvardecs(SCOPE* s, VARDEC* v) {
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs) { addany(s, v, vardec, v->debug, v->names);
CLASSVARDEC* next; if(v->next != NULL)
while(vs != NULL) { addvardecs(s, v->next);
next = vs->next;
addclassvardec(s, vs);
vs = next;
}
} }
void addvardecs(SCOPE* s, VARDEC* vs) { void addsubroutdecs(SCOPE* s, SUBROUTDEC* sd) {
VARDEC* next; addany(s, sd, subroutdec, sd->debug, onestr(sd->name));
while(vs != NULL) { if(sd->next != NULL)
next = vs->next; addsubroutdecs(s, sd->next);
addvardec(s, vs);
vs = next;
}
}
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss) {
SUBROUTDEC* next;
while(ss != NULL) {
next = ss->next;
addsubroutdec(s, ss);
ss = next;
}
} }
void addclasses(SCOPE* s, CLASS* c) { void addclasses(SCOPE* s, CLASS* c) {
CLASS* next; addany(s, c, class, c->debug, onestr(c->name));
while(c != NULL) { if(c->next != NULL)
next = c->next; addclasses(s, c->next);
addclass(s, c); }
c = next;
} void addparameters(SCOPE* s, PARAMETER* p) {
addany(s, p, parameter, p->debug, onestr(p->name));
if(p->next != NULL)
addparameters(s, p->next);
} }

View File

@ -9,35 +9,30 @@
* certain semantic rules. */ * certain semantic rules. */
// Data types // Data types
typedef struct scope {
SUBROUTDEC* subroutines;
CLASSVARDEC* classvardecs;
VARDEC* vardecs;
CLASS* classes;
int condlabelcount;
struct scope* previous;
} SCOPE;
typedef enum { typedef enum {
subroutdec, classvardec, vardec, class subroutdec, classvardec, vardec, class, parameter
} OBJTYPE; } OBJTYPE;
typedef struct object { typedef struct object {
void* pointer;
DEBUGINFO* debug;
STRINGLIST* names;
OBJTYPE type; OBJTYPE type;
union { struct object* next;
SUBROUTDEC* subroutdec;
CLASSVARDEC* classvardec;
VARDEC* vardec;
CLASS* class;
};
DEBUGINFO* (*getdebug)(struct object*);
} OBJ; } OBJ;
typedef struct scope {
OBJ* objects;
int condlabelcount;
struct scope* previous;
} SCOPE;
// Group adding // Group adding
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs); void addclassvardecs(SCOPE* s, CLASSVARDEC* vs);
void addvardecs(SCOPE* s, VARDEC* vs); void addvardecs(SCOPE* s, VARDEC* vs);
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss); void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss);
void addclasses(SCOPE* s, CLASS* c); void addclasses(SCOPE* s, CLASS* c);
void addparameters(SCOPE* s, PARAMETER* p);
// Scope handling // Scope handling
SCOPE* mkscope(SCOPE* prev); SCOPE* mkscope(SCOPE* prev);

View File

@ -257,8 +257,10 @@ LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
} }
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) { LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
// missing scope and vardecs handling SCOPE* myscope = mkscope(s);
LINEBLOCK* head = compilestatements(s, c, b->statements); if(b->vardecs != NULL)
addvardecs(s, b->vardecs);
LINEBLOCK* head = compilestatements(myscope, c, b->statements);
return head; return head;
} }
@ -291,8 +293,10 @@ LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
SCOPE* topscope = mkscope(c->globalscope); SCOPE* topscope = mkscope(c->globalscope);
addclassvardecs(topscope, class->vardecs); if(class->vardecs != NULL)
addsubroutdecs(topscope, class->subroutdecs); addclassvardecs(topscope, class->vardecs);
if(class->subroutdecs != NULL)
addsubroutdecs(topscope, class->subroutdecs);
LINEBLOCK* output = NULL; LINEBLOCK* output = NULL;
SUBROUTDEC* curr = class->subroutdecs; SUBROUTDEC* curr = class->subroutdecs;
@ -305,7 +309,7 @@ LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
void compile(COMPILER* c) { void compile(COMPILER* c) {
LINEBLOCK* output = NULL; LINEBLOCK* output = NULL;
CLASS* curr = c->globalscope->classes; CLASS* curr = c->classes;
while(curr != NULL) { while(curr != NULL) {
output = mergelnblks(output, compileclass(c, curr)); output = mergelnblks(output, compileclass(c, curr));
curr = curr->next; curr = curr->next;
@ -317,5 +321,6 @@ COMPILER* mkcompiler(CLASS* classes) {
COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER)); COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER));
c->globalscope = mkscope(NULL); c->globalscope = mkscope(NULL);
addclasses(c->globalscope, classes); addclasses(c->globalscope, classes);
c->classes = classes;
return c; return c;
} }

View File

@ -5,6 +5,7 @@
#include "vm-lines.h" #include "vm-lines.h"
typedef struct { typedef struct {
CLASS* classes;
SCOPE* globalscope; SCOPE* globalscope;
LINEBLOCK* output; LINEBLOCK* output;
} COMPILER; } COMPILER;

View File

@ -87,11 +87,16 @@ CLASSVARDEC* parseclassvardec(PARSER* p) {
CLASSVARDEC* parseclassvardecs(PARSER* p) { CLASSVARDEC* parseclassvardecs(PARSER* p) {
CLASSVARDEC* head = parseclassvardec(p); CLASSVARDEC* head = parseclassvardec(p);
if(head != NULL)
head->base->index = 0;
int index = 1;
CLASSVARDEC* curr = head; CLASSVARDEC* curr = head;
CLASSVARDEC* next; CLASSVARDEC* nextc;
while(next = parseclassvardec(p), next != NULL) { while(nextc = parseclassvardec(p), nextc != NULL) {
curr->next = next; nextc->base->index = index;
curr= next; index++;
curr->next = nextc;
curr = nextc;
} }
if(curr != NULL) if(curr != NULL)
curr->next = NULL; curr->next = NULL;
@ -136,10 +141,10 @@ SUBROUTDEC* parsesubroutdec(PARSER* p) {
SUBROUTDEC* parsesubroutdecs(PARSER* p) { SUBROUTDEC* parsesubroutdecs(PARSER* p) {
SUBROUTDEC* head = parsesubroutdec(p); SUBROUTDEC* head = parsesubroutdec(p);
SUBROUTDEC* curr = head; SUBROUTDEC* curr = head;
SUBROUTDEC* next; SUBROUTDEC* nexts;
while(next = parsesubroutdec(p), next != NULL) { while(nexts = parsesubroutdec(p), nexts != NULL) {
curr->next = next; curr->next = nexts;
curr = next; curr = nexts;
} }
if(curr != NULL) if(curr != NULL)
curr->next = NULL; curr->next = NULL;
@ -150,6 +155,7 @@ PARAMETER* parseparameter(PARSER* p) {
PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER)); PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER));
if(equals(p, ")")) if(equals(p, ")"))
return NULL; return NULL;
param->debug = getdebug(p);
param->type = parsetype(p); param->type = parsetype(p);
param->name = parseidentifier(p); param->name = parseidentifier(p);
return param; return param;
@ -157,10 +163,19 @@ PARAMETER* parseparameter(PARSER* p) {
PARAMETER* parseparameters(PARSER* p) { PARAMETER* parseparameters(PARSER* p) {
PARAMETER* head = parseparameter(p); PARAMETER* head = parseparameter(p);
if(head != NULL)
head->index = 0;
int index = 1;
PARAMETER* curr = head; PARAMETER* curr = head;
PARAMETER* nextp;
while(equals(p, ",")) { while(equals(p, ",")) {
next(p); next(p);
curr->next = parseparameter(p); nextp = parseparameter(p);
if(nextp == NULL)
unexpected(p);
nextp->index = index;
curr->next = nextp;
index++;
curr = curr->next; curr = curr->next;
} }
if(curr != NULL) if(curr != NULL)
@ -231,11 +246,16 @@ VARDEC* parsevardec(PARSER* p) {
VARDEC* parsevardecs(PARSER* p) { VARDEC* parsevardecs(PARSER* p) {
VARDEC* head = parsevardec(p); VARDEC* head = parsevardec(p);
if(head != NULL)
head->index = 0;
int index = 1;
VARDEC* curr = head; VARDEC* curr = head;
VARDEC* next; VARDEC* nextv;
while(next = parsevardec(p), next != NULL) { while(nextv = parsevardec(p), nextv != NULL) {
curr->next = next; nextv->index = index;
curr = next; index++;
curr->next = nextv;
curr = nextv;
} }
if(curr != NULL) if(curr != NULL)
curr->next = NULL; curr->next = NULL;

View File

@ -60,6 +60,8 @@ typedef struct subroutdec {
typedef struct parameter { typedef struct parameter {
char* type; char* type;
char* name; char* name;
int index;
DEBUGINFO* debug;
struct parameter* next; struct parameter* next;
} PARAMETER; } PARAMETER;
@ -71,10 +73,11 @@ typedef struct subroutbody {
typedef struct vardec { typedef struct vardec {
char* type; char* type;
bool primitive; bool primitive;
int index;
TOKENTYPE typeclass; TOKENTYPE typeclass;
STRINGLIST* names; STRINGLIST* names;
struct vardec* next;
DEBUGINFO* debug; DEBUGINFO* debug;
struct vardec* next;
} VARDEC; } VARDEC;
// Statements // Statements

7
util.c
View File

@ -40,6 +40,13 @@ char* itoa(int i) {
return a; return a;
} }
STRINGLIST* onestr(const char* str) {
STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST));
strlist->content = ezheapstr(str);
strlist->next = NULL;
return strlist;
}
STRINGLIST* initstrlist(const char** strs, int count) { STRINGLIST* initstrlist(const char** strs, int count) {
STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST)); STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST));
STRINGLIST* curr = strlist; STRINGLIST* curr = strlist;

1
util.h
View File

@ -28,6 +28,7 @@ int countplaces(int n);
char* itoa(int i); char* itoa(int i);
void* copy(void* v, int size); void* copy(void* v, int size);
STRINGLIST* onestr(const char* str);
STRINGLIST* initstrlist(const char** strs, int count); STRINGLIST* initstrlist(const char** strs, int count);
void printstrlist(STRINGLIST* strlist, FILE* stream); void printstrlist(STRINGLIST* strlist, FILE* stream);
void freestrlist(STRINGLIST* strlist); void freestrlist(STRINGLIST* strlist);