From ddd7fb04673c7c04003de786ce83025a41c69fd1 Mon Sep 17 00:00:00 2001 From: Thomas Lindner Date: Sat, 7 Jan 2023 17:10:03 +0100 Subject: [PATCH] add C style for loop --- bootstrap/emit.cc | 44 +++++++++++++++++++++++++++++++----------- bootstrap/typecheck.cc | 35 +++++++++++++++++++++++---------- bootstrap/xlang.g4 | 2 ++ test/fib.x | 8 ++------ test/sieve.x | 8 ++------ 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/bootstrap/emit.cc b/bootstrap/emit.cc index 5cfdbfb..fc358dd 100644 --- a/bootstrap/emit.cc +++ b/bootstrap/emit.cc @@ -56,43 +56,65 @@ std::any EmitVisitor::visitStatement(xlangParser::StatementContext *ctx) { int block = blockcount++; loopstack.push_back(block); - output << "@while" << block << "_expr" << std::endl; + output << "@loop" << block << "_continue" << std::endl; + output << "@loop" << block << "_expr" << std::endl; tmpcount = 0; visitCondition(ctx->condition()); - output << " jnz " << last << ", @while" << block << "_body, @while" - << block << "_end" << std::endl; - output << "@while" << block << "_body" << std::endl; + output << " jnz " << last << ", @loop" << block << "_body, @loop" << block + << "_end" << std::endl; + output << "@loop" << block << "_body" << std::endl; visitBlock(ctx->block(0)); - output << " jmp @while" << block << "_expr" << std::endl; - output << "@while" << block << "_end" << std::endl; + output << " jmp @loop" << block << "_expr" << std::endl; + output << "@loop" << block << "_end" << std::endl; + loopstack.pop_back(); + return {}; + } + if (ctx->For()) { + int block = blockcount++; + + loopstack.push_back(block); + tmpcount = 0; + visitValue(ctx->value(0)); + output << "@loop" << block << "_expr" << std::endl; + tmpcount = 0; + visitCondition(ctx->condition()); + output << " jnz " << last << ", @loop" << block << "_body, @loop" << block + << "_end" << std::endl; + output << "@loop" << block << "_body" << std::endl; + visitBlock(ctx->block(0)); + output << "@loop" << block << "_continue" << std::endl; + tmpcount = 0; + visitValue(ctx->value(1)); + output << " jmp @loop" << block << "_expr" << std::endl; + output << "@loop" << block << "_end" << std::endl; loopstack.pop_back(); return {}; } if (ctx->Break()) { - output << " jmp @while" << loopstack.back() << "_end" << std::endl; + output << " jmp @loop" << loopstack.back() << "_end" << std::endl; output << "@dead" << blockcount++ << std::endl; return {}; } if (ctx->Continue()) { - output << " jmp @while" << loopstack.back() << "_expr" << std::endl; + output << " jmp @loop" << loopstack.back() << "_expr" << std::endl; output << "@dead" << blockcount++ << std::endl; return {}; } if (ctx->Return()) { tmpcount = 0; - visitValue(ctx->value()); + visitValue(ctx->value(0)); output << " ret " << last << std::endl; output << "@dead" << blockcount++ << std::endl; return {}; } if (ctx->Print()) { tmpcount = 0; - visitValue(ctx->value()); + visitValue(ctx->value(0)); output << " call $printf(l $printformat, ..., w " << last << ")" << std::endl; return {}; } - visitValue(ctx->value()); + visitValue(ctx->value(0)); return {}; } diff --git a/bootstrap/typecheck.cc b/bootstrap/typecheck.cc index 9e75038..69e2f29 100644 --- a/bootstrap/typecheck.cc +++ b/bootstrap/typecheck.cc @@ -75,22 +75,37 @@ std::any TypeCheckVisitor::visitBlock(xlangParser::BlockContext *ctx) { } std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) { - if (auto condition = ctx->condition()) { + if (ctx->If()) { + scope.enter(); + auto condition = ctx->condition(); auto type = std::any_cast(visitCondition(condition)); - if (type != Type::Boolean) { errorlistener.typeMismatch(condition->getStart(), Type::Boolean, type); } - if (ctx->While()) { - loopcount++; - } visitBlock(ctx->block(0)); - if (ctx->While()) { - loopcount--; - } if (ctx->Else()) { visitBlock(ctx->block(1)); } + scope.leave(); + return {}; + } + if (ctx->While() || ctx->For()) { + scope.enter(); + if (ctx->For()) { + visitValue(ctx->value(0)); + } + auto condition = ctx->condition(); + auto type = std::any_cast(visitCondition(condition)); + if (type != Type::Boolean) { + errorlistener.typeMismatch(condition->getStart(), Type::Boolean, type); + } + if (ctx->For()) { + visitValue(ctx->value(1)); + } + loopcount++; + visitBlock(ctx->block(0)); + loopcount--; + scope.leave(); return {}; } if (ctx->Break()) { @@ -106,10 +121,10 @@ std::any TypeCheckVisitor::visitStatement(xlangParser::StatementContext *ctx) { return {}; } if (ctx->Return()) { - auto type = std::any_cast(visitValue(ctx->value())); + auto type = std::any_cast(visitValue(ctx->value(0))); if (type != returntype) { - errorlistener.typeMismatch(ctx->value()->getStart(), returntype, type); + errorlistener.typeMismatch(ctx->value(0)->getStart(), returntype, type); } } visitChildren(ctx); diff --git a/bootstrap/xlang.g4 b/bootstrap/xlang.g4 index 3b32a1b..2eb22e8 100644 --- a/bootstrap/xlang.g4 +++ b/bootstrap/xlang.g4 @@ -9,6 +9,7 @@ type : TypeInteger block : LeftBrace statement* RightBrace; statement : If condition block (Else block)? | While condition block + | For value Semicolon condition Semicolon value block | Break Semicolon | Continue Semicolon | Return value Semicolon @@ -54,6 +55,7 @@ TypeBoolean : 'bool'; If : 'if'; Else : 'else'; While : 'while'; +For : 'for'; Break : 'break'; Continue : 'continue'; Return : 'return'; diff --git a/test/fib.x b/test/fib.x index c785953..9222d17 100644 --- a/test/fib.x +++ b/test/fib.x @@ -1,9 +1,7 @@ main() : int { - i := 0; - while i < 10 { + for i := 0; i < 10; i =+ 1 { print fib_rec(i); print fib_iter(i); - i =+ 1; } } @@ -17,12 +15,10 @@ fib_rec(n : int) : int { fib_iter(n : int) : int { x0 := 1; x1 := 1; - i := 0; - while i < n { + for i := 0; i < n; i =+ 1 { t := x0 + x1; x0 = x1; x1 = t; - i =+ 1; } return x0; } diff --git a/test/sieve.x b/test/sieve.x index f97ec62..eba644c 100644 --- a/test/sieve.x +++ b/test/sieve.x @@ -1,19 +1,15 @@ main() : int { print 2; - i := 3; - while i < 100 { + for i := 3; i < 100; i =+ 2 { composite := false; - j := 3; - while j < i { + for j := 3; j < i; j =+ 2 { if i % j == 0 { composite = true; break; } - j =+ 2; } if not composite { print i; } - i =+ 2; } }