From 8d826326fa3358b7703afc62eb42d8205a0625b7 Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 28 Apr 2026 01:15:57 +0300 Subject: [PATCH] Add for-loop AST --- src/ast.cpp | 11 +++++++++++ src/ast.h | 27 +++++++++++++++++++++++++++ src/codegen.cpp | 9 +++++++++ src/stack_allocator.cpp | 7 +++++++ src/typechecker.cpp | 21 +++++++++++++++++++++ test.c | 6 +++--- 6 files changed, 78 insertions(+), 3 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index 03d20fe..cd3f1f8 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -137,6 +137,17 @@ namespace AST { return out.str(); } + std::string ForStatement::formatted() { + std::stringstream out{ "" }; + out << "(" << this->m_init->formatted(); + out << ";" << this->m_cond->formatted(); + out << ";" << this->m_after->formatted(); + out << ")"; + + out << "\n then " << this->m_loop->formatted(); + return out.str(); + } + std::string ReturnStatement::formatted() { std::stringstream out{ "" }; out << "return "; diff --git a/src/ast.h b/src/ast.h index aefaa36..9f7dd4f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -427,6 +427,33 @@ namespace AST { virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; + class ForStatement : public Statement { + private: + std::unique_ptr m_init; + std::unique_ptr m_cond; + std::unique_ptr m_after; + std::unique_ptr m_loop; + public: + ForStatement(token::Metadata meta, + std::unique_ptr init, + std::unique_ptr cond, + std::unique_ptr after, + std::unique_ptr loop, + std::optional> else_statement) + : Statement{ meta } + , m_init{ std::move(init) } + , m_cond{ std::move(cond) } + , m_after{ std::move(after) } + , m_loop{ std::move(loop) } { + } + virtual ~ForStatement() override = default; + virtual std::string formatted() override; + virtual void codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; + virtual void typecheck_preprocess(typecheck::Scope& scope) override; + virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; + }; + class TopLevelStatement : public Node { public: TopLevelStatement(token::Metadata meta) : Node{ meta } {} diff --git a/src/codegen.cpp b/src/codegen.cpp index 84a739d..1e7b560 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -557,6 +557,15 @@ namespace AST { builder.builder->SetInsertPoint(after_block); } + void ForStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) { + if (!builder.block) + return; + + builder.builder->SetInsertPoint(builder.block); + + throw CompileError("TODO", this->m_meta); + } + void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) { std::shared_ptr ret_ty_ptr{ this->m_return_ty }; diff --git a/src/stack_allocator.cpp b/src/stack_allocator.cpp index 2e3b142..b7e6805 100644 --- a/src/stack_allocator.cpp +++ b/src/stack_allocator.cpp @@ -93,4 +93,11 @@ namespace AST { (*this->m_else)->codegen_alloca(allocator); } } + + void ForStatement::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_init->codegen_alloca(allocator); + this->m_cond->codegen_alloca(allocator); + this->m_after->codegen_alloca(allocator); + this->m_loop->codegen_alloca(allocator); + } } \ No newline at end of file diff --git a/src/typechecker.cpp b/src/typechecker.cpp index cab217e..81b94f2 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -631,6 +631,27 @@ namespace AST { } } + void ForStatement::typecheck_preprocess(typecheck::Scope& scope) { + this->m_init->typecheck_preprocess(scope); + this->m_cond->typecheck_preprocess(scope); + this->m_after->typecheck_preprocess(scope); + this->m_loop->typecheck_preprocess(scope); + } + + void ForStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) { + auto bool_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::Bool } }; + + this->m_init->typecheck(state, scope); + auto cond_ty = this->m_cond->typecheck(state, scope, bool_ty).type; + + auto check_res = check_type(state, cond_ty, bool_ty); + this->m_cond = handle_res(std::move(this->m_cond), check_res, state); + + this->m_after->typecheck(state, scope, {}); + this->m_loop->typecheck(state, scope); + } + void Function::typecheck_preprocess(typecheck::Scope& scope) { this->m_return_ty = refresh_type(scope, this->m_return_ty); for (auto& param : this->m_params) { diff --git a/test.c b/test.c index bdb6e70..63b7d6b 100644 --- a/test.c +++ b/test.c @@ -51,9 +51,9 @@ int main() { twod_array[0][0] = 50; printf("2d array: %d!\n", twod_array[0][0]); - int counter = 0; - int a = -500; - printf("a: %d\n", a); + for (int counter = 0; counter < 10; counter++) { + printf("counter: %d\n", counter); + } return 0; } \ No newline at end of file