better loop control

This commit is contained in:
Thomas Lindner 2023-01-07 17:43:25 +01:00
parent ddd7fb0467
commit 61dbff27b3
6 changed files with 70 additions and 14 deletions

View file

@ -91,12 +91,24 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
return {}; return {};
} }
if (ctx->Break()) { if (ctx->Break()) {
if (auto integer = ctx->Integer()) {
auto num = stoul(integer->getSymbol()->getText());
output << " jmp @loop" << *(loopstack.end() - num) << "_end"
<< std::endl;
} else {
output << " jmp @loop" << loopstack.back() << "_end" << std::endl; output << " jmp @loop" << loopstack.back() << "_end" << std::endl;
}
output << "@dead" << blockcount++ << std::endl; output << "@dead" << blockcount++ << std::endl;
return {}; return {};
} }
if (ctx->Continue()) { if (ctx->Continue()) {
output << " jmp @loop" << loopstack.back() << "_expr" << std::endl; if (auto integer = ctx->Integer()) {
auto num = stoul(integer->getSymbol()->getText());
output << " jmp @loop" << *(loopstack.end() - num) << "_continue"
<< std::endl;
} else {
output << " jmp @loop" << loopstack.back() << "_continue" << std::endl;
}
output << "@dead" << blockcount++ << std::endl; output << "@dead" << blockcount++ << std::endl;
return {}; return {};
} }

View file

@ -18,11 +18,34 @@ bool ErrorListener::hasError() {
return has_error; return has_error;
} }
void ErrorListener::breakTooMany(antlr4::Token *token, size_t num, size_t max) {
printError(token->getLine(), token->getCharPositionInLine(),
"tried to break " + std::to_string(num) + " loops, but only " +
std::to_string(max) + " surrounding loops");
}
void ErrorListener::breakZero(antlr4::Token *token) {
printError(token->getLine(), token->getCharPositionInLine(),
"tried to break zero loops");
}
void ErrorListener::compilerError(const std::string &file, size_t line) { void ErrorListener::compilerError(const std::string &file, size_t line) {
std::cerr << "compiler bug in " << file << ":" << line << std::endl; std::cerr << "compiler bug in " << file << ":" << line << std::endl;
std::terminate(); std::terminate();
} }
void ErrorListener::continueTooMany(antlr4::Token *token, size_t num,
size_t max) {
printError(token->getLine(), token->getCharPositionInLine(),
"tried to continue " + std::to_string(num) + " loops, but only " +
std::to_string(max) + " surrounding loops");
}
void ErrorListener::continueZero(antlr4::Token *token) {
printError(token->getLine(), token->getCharPositionInLine(),
"tried to continue zero loops");
}
void ErrorListener::duplicateFunction(antlr4::Token *token, void ErrorListener::duplicateFunction(antlr4::Token *token,
const std::string &name) { const std::string &name) {
printError(token->getLine(), token->getCharPositionInLine(), printError(token->getLine(), token->getCharPositionInLine(),

View file

@ -17,7 +17,11 @@ class ErrorListener : public antlr4::BaseErrorListener {
bool hasError(); bool hasError();
void breakTooMany(antlr4::Token *token, size_t num, size_t max);
void breakZero(antlr4::Token *token);
[[noreturn]] void compilerError(const std::string &file, size_t line); [[noreturn]] void compilerError(const std::string &file, size_t line);
void continueTooMany(antlr4::Token *token, size_t num, size_t max);
void continueZero(antlr4::Token *token);
void duplicateFunction(antlr4::Token *token, const std::string &name); void duplicateFunction(antlr4::Token *token, const std::string &name);
void loopControlWithoutLoop(antlr4::Token *token); void loopControlWithoutLoop(antlr4::Token *token);
void shadowedVariable(antlr4::Token *token, const std::string &name); void shadowedVariable(antlr4::Token *token, const std::string &name);

View file

@ -109,15 +109,36 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
return {}; return {};
} }
if (ctx->Break()) { if (ctx->Break()) {
if (auto integer = ctx->Integer()) {
auto num = stoul(integer->getSymbol()->getText());
if (!num) {
errorlistener.breakZero(ctx->Break()->getSymbol());
}
if (num > loopcount) {
errorlistener.breakTooMany(ctx->Break()->getSymbol(), num, loopcount);
}
} else {
if (!loopcount) { if (!loopcount) {
errorlistener.loopControlWithoutLoop(ctx->Break()->getSymbol()); errorlistener.loopControlWithoutLoop(ctx->Break()->getSymbol());
} }
}
return {}; return {};
} }
if (ctx->Continue()) { if (ctx->Continue()) {
if (auto integer = ctx->Integer()) {
auto num = stoul(integer->getSymbol()->getText());
if (!num) {
errorlistener.continueZero(ctx->Break()->getSymbol());
}
if (num > loopcount) {
errorlistener.continueTooMany(ctx->Break()->getSymbol(), num,
loopcount);
}
} else {
if (!loopcount) { if (!loopcount) {
errorlistener.loopControlWithoutLoop(ctx->Continue()->getSymbol()); errorlistener.loopControlWithoutLoop(ctx->Continue()->getSymbol());
} }
}
return {}; return {};
} }
if (ctx->Return()) { if (ctx->Return()) {

View file

@ -10,8 +10,8 @@ block : LeftBrace statement* RightBrace;
statement : If condition block (Else block)? statement : If condition block (Else block)?
| While condition block | While condition block
| For value Semicolon condition Semicolon value block | For value Semicolon condition Semicolon value block
| Break Semicolon | Break Integer? Semicolon
| Continue Semicolon | Continue Integer? Semicolon
| Return value Semicolon | Return value Semicolon
| Print value Semicolon | Print value Semicolon
| value Semicolon | value Semicolon

View file

@ -1,15 +1,11 @@
main() : int { main() : int {
print 2; print 2;
for i := 3; i < 100; i =+ 2 { for i := 3; i < 100; i =+ 2 {
composite := false;
for j := 3; j < i; j =+ 2 { for j := 3; j < i; j =+ 2 {
if i % j == 0 { if i % j == 0 {
composite = true; continue 2;
break;
} }
} }
if not composite {
print i; print i;
} }
}
} }