1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-02 22:49:37 +00:00

Better error when encountering continue in switch that is not inside loop. Closes #282

This commit is contained in:
jespergravgaard 2019-08-25 15:01:04 +02:00
parent 0fb90dc8b7
commit bfe90bdf04
2 changed files with 20 additions and 13 deletions

View File

@ -855,8 +855,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** The label that a continue will jump to. Null if no continue has been encountered. */ /** The label that a continue will jump to. Null if no continue has been encountered. */
Label continueLabel; Label continueLabel;
public Loop(Scope loopScope) { /** true if the loop is a switch-statement. */
boolean isSwitch;
public Loop(Scope loopScope, boolean isSwitch) {
this.loopScope = loopScope; this.loopScope = loopScope;
this.isSwitch = isSwitch;
} }
Label getBreakLabel() { Label getBreakLabel() {
@ -895,7 +899,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
// Create the block scope early - to keep all statements of the loop inside it // Create the block scope early - to keep all statements of the loop inside it
BlockScope blockScope = getCurrentScope().addBlockScope(); BlockScope blockScope = getCurrentScope().addBlockScope();
scopeStack.push(blockScope); scopeStack.push(blockScope);
loopStack.push(new Loop(blockScope)); loopStack.push(new Loop(blockScope, false));
Label beginJumpLabel = getCurrentScope().addLabelIntermediate(); Label beginJumpLabel = getCurrentScope().addLabelIntermediate();
Label doJumpLabel = getCurrentScope().addLabelIntermediate(); Label doJumpLabel = getCurrentScope().addLabelIntermediate();
Label endJumpLabel = getCurrentScope().addLabelIntermediate(); Label endJumpLabel = getCurrentScope().addLabelIntermediate();
@ -930,7 +934,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
// Create the block scope early - to keep all statements of the loop inside it // Create the block scope early - to keep all statements of the loop inside it
BlockScope blockScope = getCurrentScope().addBlockScope(); BlockScope blockScope = getCurrentScope().addBlockScope();
scopeStack.push(blockScope); scopeStack.push(blockScope);
loopStack.push(new Loop(blockScope)); loopStack.push(new Loop(blockScope, false));
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx)); List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
Label beginJumpLabel = getCurrentScope().addLabelIntermediate(); Label beginJumpLabel = getCurrentScope().addLabelIntermediate();
StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.doWhile(ctx), comments); StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.doWhile(ctx), comments);
@ -957,7 +961,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
// Create a block scope - to keep all statements of the loop inside it // Create a block scope - to keep all statements of the loop inside it
BlockScope blockScope = getCurrentScope().addBlockScope(); BlockScope blockScope = getCurrentScope().addBlockScope();
scopeStack.push(blockScope); scopeStack.push(blockScope);
Loop switchLoop = new Loop(blockScope); Loop switchLoop = new Loop(blockScope, true);
if(containingLoop != null) { if(containingLoop != null) {
switchLoop.setContinueLabel(containingLoop.getOrCreateContinueLabel()); switchLoop.setContinueLabel(containingLoop.getOrCreateContinueLabel());
} }
@ -1030,7 +1034,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
public Object visitForClassic(KickCParser.ForClassicContext ctx) { public Object visitForClassic(KickCParser.ForClassicContext ctx) {
BlockScope blockScope = getCurrentScope().addBlockScope(); BlockScope blockScope = getCurrentScope().addBlockScope();
scopeStack.push(blockScope); scopeStack.push(blockScope);
loopStack.push(new Loop(blockScope)); loopStack.push(new Loop(blockScope, false));
// Add initialization // Add initialization
this.visit(ctx.forClassicInit()); this.visit(ctx.forClassicInit());
KickCParser.StmtForContext stmtForCtx = (KickCParser.StmtForContext) ctx.getParent(); KickCParser.StmtForContext stmtForCtx = (KickCParser.StmtForContext) ctx.getParent();
@ -1086,7 +1090,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
public Object visitForRange(KickCParser.ForRangeContext ctx) { public Object visitForRange(KickCParser.ForRangeContext ctx) {
BlockScope blockScope = getCurrentScope().addBlockScope(); BlockScope blockScope = getCurrentScope().addBlockScope();
scopeStack.push(blockScope); scopeStack.push(blockScope);
loopStack.push(new Loop(blockScope)); loopStack.push(new Loop(blockScope, false));
StatementSource statementSource = StatementSource.forRanged(ctx); StatementSource statementSource = StatementSource.forRanged(ctx);
@ -1194,7 +1198,15 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
throw new CompileError("Continue not inside a loop! ", new StatementSource(ctx)); throw new CompileError("Continue not inside a loop! ", new StatementSource(ctx));
} }
Loop currentLoop = loopStack.peek(); Loop currentLoop = loopStack.peek();
Label continueLabel = currentLoop.getOrCreateContinueLabel(); Label continueLabel;
if(currentLoop.isSwitch) {
continueLabel = currentLoop.getContinueLabel();
if(continueLabel==null) {
throw new CompileError("Continue not inside a loop! ", new StatementSource(ctx));
}
} else {
continueLabel = currentLoop.getOrCreateContinueLabel();
}
Statement continueJmpStmt = new StatementJump(continueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS); Statement continueJmpStmt = new StatementJump(continueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS);
sequence.addStatement(continueJmpStmt); sequence.addStatement(continueJmpStmt);
return null; return null;

View File

@ -36,7 +36,6 @@ public class TestPrograms {
public TestPrograms() { public TestPrograms() {
} }
@Test @Test
public void testAsmMnemonicNames() throws IOException, URISyntaxException { public void testAsmMnemonicNames() throws IOException, URISyntaxException {
compileAndCompare("asm-mnemonic-names"); compileAndCompare("asm-mnemonic-names");
@ -47,7 +46,6 @@ public class TestPrograms {
compileAndCompare("parse-negated-struct-ref"); compileAndCompare("parse-negated-struct-ref");
} }
@Test @Test
public void testLongPointer1() throws IOException, URISyntaxException { public void testLongPointer1() throws IOException, URISyntaxException {
compileAndCompare("long-pointer-1"); compileAndCompare("long-pointer-1");
@ -124,13 +122,10 @@ public class TestPrograms {
// compileAndCompare("loophead-problem"); // compileAndCompare("loophead-problem");
//} //}
// TODO: Fail with proper error when continue is encountered without a loop https://gitlab.com/camelot/kickc/issues/282
/*
@Test @Test
public void testSwitch3Err() throws IOException, URISyntaxException { public void testSwitch3Err() throws IOException, URISyntaxException {
compileAndCompare("switch-3-err"); assertError("switch-3-err", "Continue not inside a loop!");
} }
*/
@Test @Test
public void testSwitch4() throws IOException, URISyntaxException { public void testSwitch4() throws IOException, URISyntaxException {