better loop control
This commit is contained in:
parent
ddd7fb0467
commit
61dbff27b3
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue