diff --git a/compiler/compiler-statements.c b/compiler/compiler-statements.c index 4043e27..db2cc29 100644 --- a/compiler/compiler-statements.c +++ b/compiler/compiler-statements.c @@ -173,3 +173,15 @@ LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) { } 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; +} diff --git a/compiler/compiler-statements.h b/compiler/compiler-statements.h index f71273b..a2868f3 100644 --- a/compiler/compiler-statements.h +++ b/compiler/compiler-statements.h @@ -6,4 +6,5 @@ * Single function for compiling statements */ LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts); +LINEBLOCK* compilestatementsretlast(SCOPE* s, STATEMENT* sts, STATEMENT** retlast); #endif diff --git a/compiler/compiler-structure.c b/compiler/compiler-structure.c index 9fa5bb6..a029282 100644 --- a/compiler/compiler-structure.c +++ b/compiler/compiler-structure.c @@ -12,7 +12,7 @@ int getobjsize(CLASS* c); LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd); // 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* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con); LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m); @@ -64,12 +64,27 @@ LINE* mksubdeclabel(CLASS* c, SUBROUTDEC* sd) { } // 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); myscope->currclass = cl; if(b->vardecs != NULL) 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); return head; } @@ -78,7 +93,7 @@ LINEBLOCK* compilefundec(SCOPE* s, CLASS* cl, SUBROUTDEC* f) { LINE* label = mksubdeclabel(cl, f); if(f->body->statements != NULL) { - LINEBLOCK* body = compilefunbody(s, cl, f->body); + LINEBLOCK* body = compilefunbody(s, cl, f); appendlnbefore(body, label); return body; } @@ -99,7 +114,7 @@ LINEBLOCK* compileconstructor(SCOPE* s, CLASS* cl, SUBROUTDEC* con) { free(size[2]); if(con->body != NULL) - return mergelnblks(blk, compilefunbody(s, cl, con->body)); + return mergelnblks(blk, compilefunbody(s, cl, con)); else return blk; } @@ -114,7 +129,7 @@ LINEBLOCK* compilemethod(SCOPE* s, CLASS* cl, SUBROUTDEC* m) { appendln(blk, mkln(poppointer)); if(m->body != NULL) - return mergelnblks(blk, compilefunbody(s, cl, m->body)); + return mergelnblks(blk, compilefunbody(s, cl, m)); else return blk; }