Add broken continue functionality

This commit is contained in:
Sofia 2026-04-30 20:21:45 +03:00
parent ddea133138
commit 6ca1641705
4 changed files with 45 additions and 22 deletions

View File

@ -11,7 +11,16 @@
namespace codegen { namespace codegen {
Scope Scope::with_lvalue() { Scope Scope::with_lvalue() {
return Scope{ this->binops, this->unops, this->casts, this->structs, this->values, true }; return Scope{
.binops = this->binops,
.unops = this->unops,
.casts = this->casts,
.structs = this->structs,
.values = this->values,
.is_lvalue = true,
.continue_bb = this->continue_bb,
.break_bb = this->break_bb,
};
} }
} }
@ -570,14 +579,19 @@ namespace AST {
auto cond_bb = llvm::BasicBlock::Create(*builder.context, "for-cond", function); auto cond_bb = llvm::BasicBlock::Create(*builder.context, "for-cond", function);
auto inner_bb = llvm::BasicBlock::Create(*builder.context, "for-inner", function); auto inner_bb = llvm::BasicBlock::Create(*builder.context, "for-inner", function);
auto after_bb = llvm::BasicBlock::Create(*builder.context, "for-after", function); auto after_bb = llvm::BasicBlock::Create(*builder.context, "for-after", function);
auto done_bb = llvm::BasicBlock::Create(*builder.context, "for-done", function);
builder.builder->CreateBr(cond_bb); builder.builder->CreateBr(cond_bb);
codegen::Scope inner_scope{ scope };
inner_scope.continue_bb = after_bb;
inner_scope.break_bb = done_bb;
// Loop conditional // Loop conditional
builder.builder->SetInsertPoint(cond_bb); builder.builder->SetInsertPoint(cond_bb);
if (this->m_cond) { if (this->m_cond) {
auto cond_res = (*this->m_cond)->codegen(builder, scope, allocator); auto cond_res = (*this->m_cond)->codegen(builder, inner_scope, allocator);
builder.builder->CreateCondBr(cond_res.value, inner_bb, after_bb); builder.builder->CreateCondBr(cond_res.value, inner_bb, done_bb);
} }
else { else {
builder.builder->CreateBr(inner_bb); builder.builder->CreateBr(inner_bb);
@ -586,14 +600,19 @@ namespace AST {
// Loop inner block // Loop inner block
builder.block = inner_bb; builder.block = inner_bb;
builder.builder->SetInsertPoint(inner_bb); builder.builder->SetInsertPoint(inner_bb);
this->m_loop->codegen(builder, scope, allocator); this->m_loop->codegen(builder, inner_scope, allocator);
builder.builder->CreateBr(after_bb);
// Loop after-part
builder.block = after_bb;
builder.builder->SetInsertPoint(after_bb);
if (this->m_after) if (this->m_after)
(*this->m_after)->codegen(builder, scope, allocator); (*this->m_after)->codegen(builder, inner_scope, allocator);
builder.builder->CreateBr(cond_bb); builder.builder->CreateBr(cond_bb);
// Loop after // Loop after
builder.block = after_bb; builder.block = done_bb;
builder.builder->SetInsertPoint(after_bb); builder.builder->SetInsertPoint(done_bb);
} }
void WhileStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) { void WhileStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
@ -641,22 +660,24 @@ namespace AST {
statement->codegen(builder, inner, allocator); statement->codegen(builder, inner, allocator);
} }
void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) {
if (!builder.block) if (!builder.block)
return; return;
builder.builder->SetInsertPoint(builder.block); builder.builder->SetInsertPoint(builder.block);
if (scope.break_bb == nullptr)
throw CompileError("TODO", this->m_meta); throw CompileError("No break_bb!", this->m_meta);
builder.builder->CreateBr(scope.break_bb);
} }
void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator&) {
if (!builder.block) if (!builder.block)
return; return;
builder.builder->SetInsertPoint(builder.block); builder.builder->SetInsertPoint(builder.block);
if (scope.continue_bb == nullptr)
throw CompileError("TODO", this->m_meta); throw CompileError("No continue_bb!", this->m_meta);
builder.builder->CreateBr(scope.continue_bb);
} }
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) { void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {

View File

@ -28,6 +28,9 @@ namespace codegen {
bool is_lvalue; bool is_lvalue;
llvm::BasicBlock* continue_bb;
llvm::BasicBlock* break_bb;
Scope with_lvalue(); Scope with_lvalue();
}; };
} }

View File

@ -140,6 +140,8 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
.structs = {}, .structs = {},
.values = {}, .values = {},
.is_lvalue = false, .is_lvalue = false,
.continue_bb = nullptr,
.break_bb = nullptr,
}; };
try { try {

15
test.c
View File

@ -63,16 +63,13 @@ int main() {
printf("for-counter: %d\n", counter); printf("for-counter: %d\n", counter);
} }
continue;
break;
// Test while-loops // Test while-loops
int counter = 0; // int counter = 0;
while (1) { // while (1) {
if (counter > 10) // if (counter > 10)
break; // break;
printf("while-counter: %d\n", counter++); // printf("while-counter: %d\n", counter++);
} // }
return 0; return 0;
} }