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 {};
}
if (ctx->Break()) {
output << " jmp @loop" << loopstack.back() << "_end" << std::endl;
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 << "@dead" << blockcount++ << std::endl;
return {};
}
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;
return {};
}

View file

@ -18,11 +18,34 @@ bool ErrorListener::hasError() {
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) {
std::cerr << "compiler bug in " << file << ":" << line << std::endl;
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,
const std::string &name) {
printError(token->getLine(), token->getCharPositionInLine(),

View file

@ -17,7 +17,11 @@ class ErrorListener : public antlr4::BaseErrorListener {
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);
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 loopControlWithoutLoop(antlr4::Token *token);
void shadowedVariable(antlr4::Token *token, const std::string &name);

View file

@ -109,14 +109,35 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
return {};
}
if (ctx->Break()) {
if (!loopcount) {
errorlistener.loopControlWithoutLoop(ctx->Break()->getSymbol());
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) {
errorlistener.loopControlWithoutLoop(ctx->Break()->getSymbol());
}
}
return {};
}
if (ctx->Continue()) {
if (!loopcount) {
errorlistener.loopControlWithoutLoop(ctx->Continue()->getSymbol());
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) {
errorlistener.loopControlWithoutLoop(ctx->Continue()->getSymbol());
}
}
return {};
}

View file

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

View file

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