diff --git a/src/ast.cpp b/src/ast.cpp index ed38c6a..14e10e7 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -173,6 +173,24 @@ namespace AST { return out.str(); } + std::string CompoundStatement::formatted() { + std::stringstream out{ "" }; + out << "{\n"; + for (auto& statement : this->m_statements) { + out << " " << statement->formatted() << "\n"; + } + out << "}"; + return out.str(); + } + + std::string BreakStatement::formatted() { + return "break;"; + } + + std::string ContinueStatement::formatted() { + return "continue;"; + } + std::string InitializationStatement::formatted() { std::stringstream out{ "" }; out << this->m_type->formatted() << " " << this->m_name; diff --git a/src/ast.h b/src/ast.h index de19e41..1b47b72 100644 --- a/src/ast.h +++ b/src/ast.h @@ -473,6 +473,52 @@ namespace AST { virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; + /** @brief a block e.g. {statement; statement;} */ + class CompoundStatement : public Statement { + private: + std::vector> m_statements; + public: + CompoundStatement(token::Metadata meta, + std::vector> statements) + : Statement{ meta } + , m_statements{ std::move(statements) } { + } + virtual ~CompoundStatement() 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; + }; + + /** @brief break-keyword */ + class BreakStatement : public Statement { + public: + BreakStatement(token::Metadata meta) + : Statement{ meta } { + } + virtual ~BreakStatement() 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; + }; + + /** @brief continue-keyword */ + class ContinueStatement : public Statement { + public: + ContinueStatement(token::Metadata meta) + : Statement{ meta } { + } + virtual ~ContinueStatement() 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 5c48cb7..729b7ff 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -630,6 +630,32 @@ namespace AST { builder.block = after_bb; } + void CompoundStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { + if (!builder.block) + return; + + builder.builder->SetInsertPoint(builder.block); + + throw CompileError("TODO", this->m_meta); + } + + void BreakStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { + if (!builder.block) + return; + + builder.builder->SetInsertPoint(builder.block); + + throw CompileError("TODO", this->m_meta); + } + + void ContinueStatement::codegen(codegen::Builder& builder, codegen::Scope&, codegen::StackAllocator&) { + 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 92a56e9..3956bd4 100644 --- a/src/stack_allocator.cpp +++ b/src/stack_allocator.cpp @@ -109,4 +109,13 @@ namespace AST { (*this->m_cond)->codegen_alloca(allocator); this->m_loop->codegen_alloca(allocator); } + + void CompoundStatement::codegen_alloca(codegen::StackAllocator& allocator) { + for (auto& statement : this->m_statements) + statement->codegen_alloca(allocator); + } + + void BreakStatement::codegen_alloca(codegen::StackAllocator&) {} + + void ContinueStatement::codegen_alloca(codegen::StackAllocator&) {} } \ No newline at end of file diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 372f79f..e1891fd 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -685,6 +685,26 @@ namespace AST { this->m_loop->typecheck(state, inner_scope); } + void CompoundStatement::typecheck_preprocess(typecheck::Scope& scope) { + typecheck::Scope inner{ scope }; + for (auto& statement : this->m_statements) { + statement->typecheck_preprocess(inner); + } + } + + void CompoundStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) { + typecheck::Scope inner{ scope }; + for (auto& statement : this->m_statements) { + statement->typecheck(state, inner); + } + } + + void BreakStatement::typecheck_preprocess(typecheck::Scope&) {} + void BreakStatement::typecheck(typecheck::State&, typecheck::Scope&) {} + + void ContinueStatement::typecheck_preprocess(typecheck::Scope&) {} + void ContinueStatement::typecheck(typecheck::State&, typecheck::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 d65545b..38f8a9b 100644 --- a/test.c +++ b/test.c @@ -62,8 +62,9 @@ int main() { // Test while-loops int counter = 0; - while (counter < 10) + while (counter < 10) { printf("while-counter: %d\n", counter++); + } return 0; } \ No newline at end of file