better loop control
This commit is contained in:
parent
ddd7fb0467
commit
61dbff27b3
|
@ -91,12 +91,24 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (ctx->Break()) {
|
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;
|
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 {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -109,14 +109,35 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (ctx->Break()) {
|
if (ctx->Break()) {
|
||||||
if (!loopcount) {
|
if (auto integer = ctx->Integer()) {
|
||||||
errorlistener.loopControlWithoutLoop(ctx->Break()->getSymbol());
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
if (ctx->Continue()) {
|
if (ctx->Continue()) {
|
||||||
if (!loopcount) {
|
if (auto integer = ctx->Integer()) {
|
||||||
errorlistener.loopControlWithoutLoop(ctx->Continue()->getSymbol());
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue