Compare commits

...

5 Commits

Author SHA1 Message Date
Augusto Gunsch 0339c25877
Fix segfault 2021-01-09 15:31:59 -03:00
Augusto Gunsch f674577437
Fix NULL statements function declarations 2021-01-07 20:54:48 -03:00
Augusto Gunsch ae03a25542
Force last function statement to be 'return' 2021-01-07 19:58:28 -03:00
Augusto Gunsch 1784599e72
Fix operation order 2021-01-07 18:11:21 -03:00
Augusto Gunsch 80a3e1ef0f
Fix segfault 2021-01-06 21:18:52 -03:00
10 changed files with 109 additions and 77 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 -Wall CFLAGS = -std=c99 -Wall -O3
OUTFILE = jack-compiler OUTFILE = jack-compiler
main: ${FILES} main: ${FILES}

View File

@ -15,10 +15,10 @@ char* toascii(char c);
// Dealing with singular terms // Dealing with singular terms
LINEBLOCK* compilestrconst(char* str); LINEBLOCK* compilestrconst(char* str);
LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t); LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t);
LINEBLOCK* compilearrayitem(SCOPE* s, TERM* t); LINEBLOCK* compilearrayitem(SCOPE* s, DEBUGINFO* d, TERM* t);
LINEBLOCK* compilecallln(SCOPE* s, SUBROUTDEC* d, SUBROUTCALL* call); LINEBLOCK* compilecallln(SCOPE* s, SUBROUTDEC* d, SUBROUTCALL* call);
LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t); LINEBLOCK* pushunaryopterm(SCOPE* s, DEBUGINFO* d, TERM* t);
LINEBLOCK* compileterm(SCOPE* s, TERM* t); LINEBLOCK* compileterm(SCOPE* s, DEBUGINFO* d, TERM* t);
/* END FORWARD DECLARATIONS */ /* END FORWARD DECLARATIONS */
@ -128,9 +128,9 @@ LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) {
return mklnblk(pushconstant(0)); return mklnblk(pushconstant(0));
} }
LINEBLOCK* compilearrayitem(SCOPE* s, TERM* t) { LINEBLOCK* compilearrayitem(SCOPE* s, DEBUGINFO* d, TERM* t) {
LINEBLOCK* blk = compileexpression(s, t->array->exp); LINEBLOCK* blk = compileexpression(s, d, t->array->exp);
appendln(blk, pushvar(s, t->array->name)); appendln(blk, pushvar(s, d, t->array->name));
appendln(blk, onetoken("add")); appendln(blk, onetoken("add"));
@ -161,7 +161,7 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
LINEBLOCK* blk = compilecallln(s, d, call); LINEBLOCK* blk = compilecallln(s, d, call);
if(call->parameters != NULL) if(call->parameters != NULL)
blk = mergelnblks(compileexplist(s, call->parameters), blk); blk = mergelnblks(compileexplist(s, call->debug, call->parameters), blk);
if(d->subroutclass == method) { if(d->subroutclass == method) {
if(call->parentname == NULL) if(call->parentname == NULL)
@ -179,8 +179,8 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
return blk; return blk;
} }
LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) { LINEBLOCK* pushunaryopterm(SCOPE* s, DEBUGINFO* d, TERM* t) {
LINEBLOCK* blk = compileexpression(s, t->expression); LINEBLOCK* blk = compileexpression(s, d, t->expression);
LINE* neg; LINE* neg;
if(t->unaryop == '-') if(t->unaryop == '-')
neg = onetoken("neg"); neg = onetoken("neg");
@ -190,36 +190,39 @@ LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
return blk; return blk;
} }
LINEBLOCK* compileterm(SCOPE* s, TERM* t) { LINEBLOCK* compileterm(SCOPE* s, DEBUGINFO* d, TERM* t) {
if(t->type == varname) return mklnblk(pushvar(s, t->string)); if(t->type == varname) return mklnblk(pushvar(s, d, t->string));
if(t->type == intconstant) return mklnblk(pushconstant(t->integer)); if(t->type == intconstant) return mklnblk(pushconstant(t->integer));
if(t->type == stringconstant) return compilestrconst(t->string); if(t->type == stringconstant) return compilestrconst(t->string);
if(t->type == keywordconstant) return compilekeywordconst(s, t); if(t->type == keywordconstant) return compilekeywordconst(s, t);
if(t->type == arrayitem) return compilearrayitem(s, t); if(t->type == arrayitem) return compilearrayitem(s, d, t);
if(t->type == subroutcall) return compilesubroutcall(s, t->call); if(t->type == subroutcall) return compilesubroutcall(s, t->call);
if(t->type == innerexpression) return compileexpression(s, t->expression); if(t->type == innerexpression) return compileexpression(s, d, t->expression);
return pushunaryopterm(s, t); return pushunaryopterm(s, d, t);
} }
// Dealing with whole expressions // Dealing with whole expressions
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) { LINEBLOCK* compileexpression(SCOPE* s, DEBUGINFO* d, TERM* e) {
LINEBLOCK* blk = NULL; LINEBLOCK* blk = NULL;
LINEBLOCK* ops = NULL;
if(e != NULL) { if(e != NULL) {
while(true) { while(true) {
blk = mergelnblks(blk, compileterm(s, e)); blk = mergelnblks(blk, compileterm(s, d, e));
if(e->next == NULL) if(e->next == NULL)
break; break;
appendln(blk, mathopln(e->op)); ops = mergelnblks(ops, mklnblk(mathopln(e->op)));
e = e->next; e = e->next;
} }
} }
if(ops != NULL)
blk = mergelnblks(blk, ops);
return blk; return blk;
} }
LINEBLOCK* compileexplist(SCOPE* s, EXPRESSIONLIST* explist) { LINEBLOCK* compileexplist(SCOPE* s, DEBUGINFO* d, EXPRESSIONLIST* explist) {
LINEBLOCK* head = NULL; LINEBLOCK* head = NULL;
while(explist != NULL) { while(explist != NULL) {
head = mergelnblks(head, compileexpression(s, explist->expression)); head = mergelnblks(head, compileexpression(s, d, explist->expression));
explist = explist->next; explist = explist->next;
} }
return head; return head;

View File

@ -10,6 +10,6 @@
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call); LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call);
// Dealing with whole expressions // Dealing with whole expressions
LINEBLOCK* compileexpression(SCOPE* s, TERM* e); LINEBLOCK* compileexpression(SCOPE* s, DEBUGINFO* d, TERM* e);
LINEBLOCK* compileexplist(SCOPE* s, EXPRESSIONLIST* explist); LINEBLOCK* compileexplist(SCOPE* s, DEBUGINFO* d, EXPRESSIONLIST* explist);
#endif #endif

View File

@ -11,7 +11,7 @@ char* memsegnames[] = { "local", "static", "argument", "this" };
// Error messages // Error messages
void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2); void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2);
void ensurenoduplicate(SCOPE* s, char* name); void ensurenoduplicate(SCOPE* s, DEBUGINFO* d, char* name);
// Getters // Getters
VAR* getvarinvars(VAR* vars, const char* name); VAR* getvarinvars(VAR* vars, const char* name);
@ -49,18 +49,18 @@ void invalidparent(SUBROUTCALL* call) {
exit(1); exit(1);
} }
void ensurenoduplicate(SCOPE* s, char* name) { void ensurenoduplicate(SCOPE* s, DEBUGINFO* d, char* name) {
VAR* v = getvar(s, name); VAR* v = getvar(s, name);
if(v != NULL) if(v != NULL)
doubledeclaration(name, s->currdebug, v->debug); doubledeclaration(name, d, v->debug);
CLASS* c = getclass(s, name); CLASS* c = getclass(s, name);
if(c != NULL) if(c != NULL)
doubledeclaration(name, s->currdebug, c->debug); doubledeclaration(name, d, c->debug);
SUBROUTDEC* sr = getsubroutdec(s, name); SUBROUTDEC* sr = getsubroutdec(s, name);
if(sr != NULL) if(sr != NULL)
doubledeclaration(name, s->currdebug, sr->debug); doubledeclaration(name, d, sr->debug);
} }
// Scope handling // Scope handling
@ -106,6 +106,13 @@ VAR* getvar(SCOPE* s, const char* name) {
return NULL; return NULL;
} }
VAR* getvarmustexist(SCOPE* s, DEBUGINFO* d, const char* name) {
VAR* v = getvar(s, name);
if(v == NULL)
notdeclared(name, d);
return v;
}
CLASS* getclass(SCOPE* s, const char* name) { CLASS* getclass(SCOPE* s, const char* name) {
CLASS* curr = s->classes; CLASS* curr = s->classes;
while(curr != NULL) { while(curr != NULL) {
@ -213,7 +220,7 @@ VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT
} }
void addvar(SCOPE* s, VAR** dest, VAR* v) { void addvar(SCOPE* s, VAR** dest, VAR* v) {
ensurenoduplicate(s, v->name); ensurenoduplicate(s, v->debug, v->name);
if(!v->primitive) { if(!v->primitive) {
CLASS* type = getclass(s, v->type); CLASS* type = getclass(s, v->type);

View File

@ -22,7 +22,6 @@ typedef struct var {
typedef struct scope { typedef struct scope {
struct compiler* compiler; struct compiler* compiler;
DEBUGINFO* currdebug;
CLASS* currclass; CLASS* currclass;
CLASS* classes; CLASS* classes;
@ -52,6 +51,7 @@ CLASS* getclass(SCOPE* s, const char* name);
// Generic getters // Generic getters
VAR* getvar(SCOPE* s, const char* name); VAR* getvar(SCOPE* s, const char* name);
VAR* getvarmustexist(SCOPE* s, DEBUGINFO* d, const char* name);
// Freeing // Freeing
void freescope(SCOPE* s); void freescope(SCOPE* s);

View File

@ -12,10 +12,10 @@ LINE* pushtemp();
char* mkcondlabel(char* name, int count); char* mkcondlabel(char* name, int count);
// Handling individual statements // Handling individual statements
LINEBLOCK* compileret(SCOPE* s, TERM* e); LINEBLOCK* compileret(SCOPE* s, STATEMENT* st);
LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st); LINEBLOCK* compileif(SCOPE* s, STATEMENT* st);
LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w); LINEBLOCK* compilewhile(SCOPE* s, STATEMENT* st);
LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l); LINEBLOCK* compilelet(SCOPE* s, STATEMENT* st);
LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st); LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st);
/* END FORWARD DECLARATIONS */ /* END FORWARD DECLARATIONS */
@ -41,7 +41,8 @@ char* mkcondlabel(char* name, int count) {
} }
// Handling individual statements // Handling individual statements
LINEBLOCK* compileret(SCOPE* s, TERM* e) { LINEBLOCK* compileret(SCOPE* s, STATEMENT* st) {
TERM* e = st->retstatement;
LINE* ret = onetoken("return"); LINE* ret = onetoken("return");
LINEBLOCK* blk = mklnblk(ret); LINEBLOCK* blk = mklnblk(ret);
@ -50,13 +51,14 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) {
char* tokens[] = { "push", "constant", "0" }; char* tokens[] = { "push", "constant", "0" };
appendlnbefore(blk, mkln(tokens)); appendlnbefore(blk, mkln(tokens));
} else } else
blk = mergelnblks(compileexpression(s, e), blk); blk = mergelnblks(compileexpression(s, st->debug, e), blk);
return blk; return blk;
} }
LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) { LINEBLOCK* compileif(SCOPE* s, STATEMENT* st) {
LINEBLOCK* blk = compileexpression(s, st->base->expression); IFSTATEMENT* ifst = st->ifstatement;
LINEBLOCK* blk = compileexpression(s, st->debug, ifst->base->expression);
pthread_mutex_lock(&(s->compiler->ifmutex)); pthread_mutex_lock(&(s->compiler->ifmutex));
static int ifcount = 0; static int ifcount = 0;
@ -75,10 +77,10 @@ LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) {
char* truelabelln[] = { "label", truelabel }; char* truelabelln[] = { "label", truelabel };
appendln(blk, mkln(truelabelln)); appendln(blk, mkln(truelabelln));
blk = mergelnblks(blk, compilestatements(s, st->base->statements)); blk = mergelnblks(blk, compilestatements(s, ifst->base->statements));
char* endlabel; char* endlabel;
bool haselse = st->elsestatements != NULL; bool haselse = ifst->elsestatements != NULL;
if(haselse) { if(haselse) {
endlabel = mkcondlabel("IF_END", mycount); endlabel = mkcondlabel("IF_END", mycount);
char* endgoto[] = { "goto", endlabel }; char* endgoto[] = { "goto", endlabel };
@ -89,7 +91,7 @@ LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) {
appendln(blk, mkln(falselabelln)); appendln(blk, mkln(falselabelln));
if(haselse) { if(haselse) {
blk = mergelnblks(blk, compilestatements(s, st->elsestatements)); blk = mergelnblks(blk, compilestatements(s, ifst->elsestatements));
char* endlabelln[] = { "label", endlabel }; char* endlabelln[] = { "label", endlabel };
appendln(blk, mkln(endlabelln)); appendln(blk, mkln(endlabelln));
free(endlabel); free(endlabel);
@ -101,8 +103,9 @@ LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) {
return blk; return blk;
} }
LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w) { LINEBLOCK* compilewhile(SCOPE* s, STATEMENT* st) {
LINEBLOCK* blk = compileexpression(s, w->expression); CONDSTATEMENT* w = st->whilestatement;
LINEBLOCK* blk = compileexpression(s, st->debug, w->expression);
pthread_mutex_lock(&(s->compiler->whilemutex)); pthread_mutex_lock(&(s->compiler->whilemutex));
static int whilecount = 0; static int whilecount = 0;
@ -134,13 +137,14 @@ LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w) {
return blk; return blk;
} }
LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) { LINEBLOCK* compilelet(SCOPE* s, STATEMENT* st) {
LINEBLOCK* blk = compileexpression(s, l->expression); LETSTATEMENT* l = st->letstatement;
LINEBLOCK* blk = compileexpression(s, st->debug, l->expression);
if(l->arrayind != NULL) { if(l->arrayind != NULL) {
appendlnbefore(blk, onetoken("add")); appendlnbefore(blk, onetoken("add"));
appendlnbefore(blk, pushvar(s, l->varname)); appendlnbefore(blk, pushvar(s, st->debug, l->varname));
blk = mergelnblks(compileexpression(s, l->arrayind), blk); blk = mergelnblks(compileexpression(s, st->debug, l->arrayind), blk);
appendln(blk, poptemp()); appendln(blk, poptemp());
appendln(blk, popthatadd()); appendln(blk, popthatadd());
@ -148,17 +152,16 @@ LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) {
appendln(blk, popthat()); appendln(blk, popthat());
} }
else else
appendln(blk, popvar(s, l->varname)); appendln(blk, popvar(s, st->debug, l->varname));
return blk; return blk;
} }
LINEBLOCK* compilestatement(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 == dostatement) return compilesubroutcall(s, st->dostatement);
if(st->type == returnstatement) return compileret(s, st->retstatement); if(st->type == returnstatement) return compileret(s, st);
if(st->type == ifstatement) return compileif(s, st->ifstatement); if(st->type == ifstatement) return compileif(s, st);
if(st->type == whilestatement) return compilewhile(s, st->whilestatement); if(st->type == whilestatement) return compilewhile(s, st);
return compilelet(s, st->letstatement); return compilelet(s, st);
} }
LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) { LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) {
@ -169,3 +172,15 @@ LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) {
} }
return head; return head;
} }
LINEBLOCK* compilestatementsretlast(SCOPE* s, STATEMENT* sts, STATEMENT** retlast) {
LINEBLOCK* head = NULL;
STATEMENT* last = NULL;
while(sts != NULL) {
head = mergelnblks(head, compilestatement(s, sts));
last = sts;
sts = sts->next;
}
*retlast = last;
return head;
}

View File

@ -6,4 +6,5 @@
* Single function for compiling statements */ * Single function for compiling statements */
LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts); LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts);
LINEBLOCK* compilestatementsretlast(SCOPE* s, STATEMENT* sts, STATEMENT** retlast);
#endif #endif

View File

@ -12,7 +12,7 @@ int getobjsize(CLASS* c);
LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd); LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd);
// Compiling methods // Compiling methods
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTBODY* b); LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTDEC* d);
LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f); LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f);
LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con); LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con);
LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m); LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m);
@ -64,12 +64,27 @@ LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd) {
} }
// Compiling methods // Compiling methods
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTBODY* b) { LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTDEC* d) {
SUBROUTBODY* b = d->body;
SCOPE* myscope = mkscope(s); SCOPE* myscope = mkscope(s);
myscope->currclass = cl; myscope->currclass = cl;
if(b->vardecs != NULL) if(b->vardecs != NULL)
addlocalvars(myscope, b->vardecs); addlocalvars(myscope, b->vardecs);
LINEBLOCK* head = compilestatements(myscope, b->statements);
if(b->statements == NULL) {
eprintf("Subroutine body has no statements; file '%s', line %i\n",
d->debug->file, d->debug->definedat);
exit(1);
}
STATEMENT* last;
LINEBLOCK* head = compilestatementsretlast(myscope, b->statements, &last);
if(last->type != returnstatement) {
eprintf("Subroutine must end with a return statement; file '%s', line %i\n",
last->debug->file, last->debug->definedat);
exit(1);
}
freescope(myscope); freescope(myscope);
return head; return head;
} }
@ -77,13 +92,9 @@ LINEBLOCK* compilefunbody(SCOPE* s, CLASS* cl, SUBROUTBODY* b) {
LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f) { LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f) {
LINE* label = mksubdeclabel(cl, f); LINE* label = mksubdeclabel(cl, f);
if(f->body->statements != NULL) { LINEBLOCK* body = compilefunbody(s, cl, f);
LINEBLOCK* body = compilefunbody(s, cl, f->body); appendlnbefore(body, label);
appendlnbefore(body, label); return body;
return body;
}
else
return mklnblk(label);
} }
LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con) { LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con) {
@ -99,7 +110,7 @@ LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con) {
free(size[2]); free(size[2]);
if(con->body != NULL) if(con->body != NULL)
return mergelnblks(blk, compilefunbody(s, cl, con->body)); return mergelnblks(blk, compilefunbody(s, cl, con));
else else
return blk; return blk;
} }
@ -114,7 +125,7 @@ LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m) {
appendln(blk, mkln(poppointer)); appendln(blk, mkln(poppointer));
if(m->body != NULL) if(m->body != NULL)
return mergelnblks(blk, compilefunbody(s, cl, m->body)); return mergelnblks(blk, compilefunbody(s, cl, m));
else else
return blk; return blk;
} }

View File

@ -8,21 +8,16 @@ LINE* opvarraw(SCOPE* s, char* op, VAR* v) {
return ln; return ln;
} }
LINE* opvar(SCOPE* s, char* op, const char* name) { LINE* pushvarraw(SCOPE* s, VAR* v) {
VAR* v = getvar(s, name);
return opvarraw(s, op, v);
}
LINE* pushvarraw(SCOPE*s, VAR* v) {
return opvarraw(s, "push", v); return opvarraw(s, "push", v);
} }
LINE* pushvar(SCOPE* s, const char* name) { LINE* pushvar(SCOPE* s, DEBUGINFO* d, const char* name) {
return opvar(s, "push", name); return opvarraw(s, "push", getvarmustexist(s, d, name));
} }
LINE* popvar(SCOPE* s, const char* name) { LINE* popvar(SCOPE* s, DEBUGINFO* d, const char* name) {
return opvar(s, "pop", name); return opvarraw(s, "pop", getvarmustexist(s, d, name));
} }
LINE* poptemp() { LINE* poptemp() {

View File

@ -12,9 +12,9 @@
LINE* onetoken(char* str); LINE* onetoken(char* str);
LINE* mksimpleln(char** tokens, int count); LINE* mksimpleln(char** tokens, int count);
LINE* pushvarraw(SCOPE*s, VAR* v); LINE* pushvarraw(SCOPE* s, VAR* v);
LINE* pushvar(SCOPE* s, const char* name); LINE* pushvar(SCOPE* s, DEBUGINFO* d, const char* name);
LINE* popvar(SCOPE* s, const char* name); LINE* popvar(SCOPE* s, DEBUGINFO* d, const char* name);
LINE* poptemp(); LINE* poptemp();
LINE* popthatadd(); LINE* popthatadd();