Implemented loops

This commit is contained in:
Rafał Grodziński
2025-06-26 15:50:18 +09:00
parent ac9205e23e
commit 293522315b
4 changed files with 58 additions and 32 deletions

View File

@@ -5,7 +5,7 @@ project(
LANGUAGES CXX C) LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_COLOR_DIAGNOSTICS ON) set(CMAKE_COLOR_DIAGNOSTICS OFF)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
find_package(LLVM REQUIRED CONFIG) find_package(LLVM REQUIRED CONFIG)

View File

@@ -127,25 +127,45 @@ void ModuleBuilder::buildReturn(shared_ptr<StatementReturn> statement) {
void ModuleBuilder::buildLoop(shared_ptr<StatementLoop> statement) { void ModuleBuilder::buildLoop(shared_ptr<StatementLoop> statement) {
shared_ptr<Statement> initStatement = statement->getInitStatement(); shared_ptr<Statement> initStatement = statement->getInitStatement();
shared_ptr<StatementBlock> bodyStatement= statement->getBodyBlockStatement();
shared_ptr<Expression> preExpression = statement->getPreConditionExpression(); shared_ptr<Expression> preExpression = statement->getPreConditionExpression();
shared_ptr<Expression> postExpression = statement->getPostConditionExpression(); shared_ptr<Expression> postExpression = statement->getPostConditionExpression();
shared_ptr<StatementBlock> bodyStatement= statement->getBodyBlockStatement();
llvm::BasicBlock *parentBlock = builder->GetInsertBlock();
llvm::Function *fun = builder->GetInsertBlock()->getParent();
llvm::BasicBlock *preBlock = llvm::BasicBlock::Create(*context, "loopPre", fun);
llvm::BasicBlock *bodyBlock = llvm::BasicBlock::Create(*context, "loopBody");
llvm::BasicBlock *afterBlock = llvm::BasicBlock::Create(*context, "loopPost");
// loop init
if (initStatement != nullptr) if (initStatement != nullptr)
buildStatement(statement->getInitStatement()); buildStatement(statement->getInitStatement());
llvm::Function *fun = builder->GetInsertBlock()->getParent(); builder->CreateBr(preBlock);
llvm::BasicBlock *bodyBlock = llvm::BasicBlock::Create(*context, "loopBody", fun); // pre condition
builder->SetInsertPoint(preBlock);
if (preExpression != nullptr) {
llvm::Value *preConditionValue = valueForExpression(preExpression);
builder->CreateCondBr(preConditionValue, bodyBlock, afterBlock);
} else {
builder->CreateBr(bodyBlock);
}
// body
fun->insert(fun->end(), bodyBlock);
builder->SetInsertPoint(bodyBlock); builder->SetInsertPoint(bodyBlock);
buildBlock(bodyStatement); buildBlock(bodyStatement);
builder->CreateBr(bodyBlock);
//llvm::BasicBlock *loopEndBlock = builder->GetInsertBlock() // post condition
if (postExpression != nullptr) {
llvm::Value *postConditionValue = valueForExpression(postExpression);
builder->CreateCondBr(postConditionValue, preBlock, afterBlock);
} else {
builder->CreateBr(preBlock);
}
builder->SetInsertPoint(parentBlock); // loop post
fun->insert(fun->end(), afterBlock);
builder->SetInsertPoint(afterBlock);
} }
void ModuleBuilder::buildMetaExternFunction(shared_ptr<StatementMetaExternFunction> statement) { void ModuleBuilder::buildMetaExternFunction(shared_ptr<StatementMetaExternFunction> statement) {

View File

@@ -183,32 +183,41 @@ shared_ptr<Statement> Parser::matchStatementLoop() {
if (!tryMatchingTokenKinds({TokenKind::REPEAT}, true, true)) if (!tryMatchingTokenKinds({TokenKind::REPEAT}, true, true))
return nullptr; return nullptr;
shared_ptr<Statement> initStatement;
shared_ptr<Expression> preConditionExpression;
shared_ptr<Expression> postConditionExpression;
// initial // initial
shared_ptr<Statement> initStatement = matchStatementVariable(); initStatement = matchStatementVariable();
if (initStatement != nullptr && !initStatement->isValid()) if (initStatement != nullptr && !initStatement->isValid())
initStatement = nullptr; initStatement = nullptr;
// got initial, expect comma if (tokens.at(currentIndex-1)->getKind() != TokenKind::NEW_LINE) {
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) // got initial, expect comma
return matchStatementInvalid("Expected comma after initial statement"); if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
return matchStatementInvalid("Expected comma after initial statement");
// pre condition // pre condition
shared_ptr<Expression> preConditionExpression = nextExpression(); preConditionExpression = nextExpression();
if (preConditionExpression != nullptr && !preConditionExpression->isValid()) if (preConditionExpression != nullptr && !preConditionExpression->isValid())
return matchStatementInvalid("Expected pre-condition expression"); return matchStatementInvalid("Expected pre-condition expression");
// post condition if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
shared_ptr<Expression> postConditionExpression; // got pre-condition, expect comma
if (tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
postConditionExpression = nextExpression(); return matchStatementInvalid("Expected comma after pre-condition statement");
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
return matchStatementInvalid("Expected post-condition expression"); // post condition
postConditionExpression = nextExpression();
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
return matchStatementInvalid("Expected post-condition expression");
// epxect new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line");
}
} }
// epxect new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line");
// body // body
shared_ptr<Statement> bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON}, true); shared_ptr<Statement> bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON}, true);
if (bodyBlockStatement == nullptr) if (bodyBlockStatement == nullptr)

View File

@@ -1,8 +1,5 @@
test fun test fun: num1 sint32, num2 sint32
/*rep i sint32 <- 0, i < 10 rep num3 sint32 <- 5, true, num1 < num2
//i sint32 <- i + 1
;*/
rep i sint32 <- 13
abc sint32 <- 5 abc sint32 <- 5
; ;
; ;