aboutsummaryrefslogtreecommitdiffstats
path: root/libacc/acc.cpp
diff options
context:
space:
mode:
authorJack Palevich <jackpal@google.com>2009-10-29 15:04:27 -0700
committerJack Palevich <jackpal@google.com>2009-10-29 15:04:27 -0700
commitc951c59232f59f1e0235725103f8636fe2f580f7 (patch)
treee1059a9401d7ff923b8440ee9b054d1ab81484ed /libacc/acc.cpp
parent0163f77a831e915bcbb7b18cde486d2b081da478 (diff)
downloadsystem_core-c951c59232f59f1e0235725103f8636fe2f580f7.tar.gz
system_core-c951c59232f59f1e0235725103f8636fe2f580f7.tar.bz2
system_core-c951c59232f59f1e0235725103f8636fe2f580f7.zip
Add support for the continue statement
Add error check for a break statement that's not inside a loop. (We just generated bad code before. Oops!)
Diffstat (limited to 'libacc/acc.cpp')
-rw-r--r--libacc/acc.cpp24
1 files changed, 17 insertions, 7 deletions
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index d9cecdd6..98401977 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -5003,7 +5003,7 @@ class Compiler : public ErrorSink {
return pGen->gtst(0, 0);
}
- void block(intptr_t l, bool outermostFunctionBlock) {
+ void block(int* breakLabel, int continueAddress, bool outermostFunctionBlock) {
intptr_t a, n, t;
Type* pBaseType;
@@ -5015,12 +5015,12 @@ class Compiler : public ErrorSink {
skip('(');
a = test_expr();
skip(')');
- block(l, false);
+ block(breakLabel, continueAddress, false);
if (tok == TOK_ELSE) {
next();
n = pGen->gjmp(0); /* jmp */
pGen->gsym(a);
- block(l, false);
+ block(breakLabel, continueAddress, false);
pGen->gsym(n); /* patch else jmp */
} else {
pGen->gsym(a); /* patch if test */
@@ -5050,7 +5050,7 @@ class Compiler : public ErrorSink {
}
}
skip(')');
- block((intptr_t) &a, false);
+ block(&a, n, false);
pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */
pGen->gsym(a);
} else if (tok == '{') {
@@ -5059,7 +5059,7 @@ class Compiler : public ErrorSink {
}
next();
while (tok != '}' && tok != EOF)
- block(l, false);
+ block(breakLabel, continueAddress, false);
skip('}');
if (! outermostFunctionBlock) {
mLocals.popLevel();
@@ -5081,7 +5081,17 @@ class Compiler : public ErrorSink {
}
rsym = pGen->gjmp(rsym); /* jmp */
} else if (accept(TOK_BREAK)) {
- *(int *) l = pGen->gjmp(*(int *) l);
+ if (breakLabel) {
+ *breakLabel = pGen->gjmp(*breakLabel);
+ } else {
+ error("break statement must be within a for, do, while, or switch statement");
+ }
+ } else if (accept(TOK_CONTINUE)) {
+ if (continueAddress) {
+ pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset());
+ } else {
+ error("continue statement must be within a for, do, or while statement");
+ }
} else if (tok != ';')
commaExpr();
skip(';');
@@ -5907,7 +5917,7 @@ class Compiler : public ErrorSink {
rsym = loc = 0;
pReturnType = pDecl->pHead;
a = pGen->functionEntry(pDecl);
- block(0, true);
+ block(0, 0, true);
pGen->gsym(rsym);
pGen->functionExit(pDecl, a, loc);
mLocals.popLevel();