From 916c169691fc5f719469e97a3e7cf7116a8d9bd0 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:24:37 +0100 Subject: [PATCH 01/35] Create ci file --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c97fc86 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake build-essential llvm-dev libcatch2-dev + + - name: Build and Test + run: | + cmake . + ./build/bin/tests From 314806729955da1445b8ecfc5a8f3a9b71d99897 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:25:02 +0100 Subject: [PATCH 02/35] Create cmake file --- CMakeLists.txt | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..08f32f7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 4.4.2) + +project(alpha) + + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include_directories(${CMAKE_SOURCE_DIR}/src) + +find_package(LLVM REQUIRED CONFIG) + +add_definitions(${LLVM_DEFINITIONS}) +llvm_map_components_to_libnames(llvm_libs + core + support + irreader + codegen + asmprinter + target + native + TargetParser +) + + +file(GLOB_RECURSE ALL_SRC_CPP CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") +list(FILTER ALL_SRC_CPP EXCLUDE REGEX ".*main\\.cpp$") + +file(GLOB_RECURSE ALL_SRC_HPP CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp") + +add_library(alpha_lib STATIC ${ALL_SRC_CPP} ${ALL_SRC_HPP}) + +target_include_directories(alpha_lib PUBLIC + ${CMAKE_SOURCE_DIR}/src + ${LLVM_INCLUDE_DIRS} +) +target_link_libraries(alpha_lib PUBLIC ${llvm_libs}) + +# Main compiler + +add_executable(main src/main.cpp) + +target_link_libraries(main PRIVATE alpha_lib) + +set_target_properties(main PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin +) + +# Tests +find_package(Catch2 3 REQUIRED) + +enable_testing() +file(GLOB_RECURSE ALL_TEST_CPP CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp") + + +add_executable(tests + ${ALL_TEST_CPP} +) + +target_link_libraries(tests PRIVATE + alpha_lib + Catch2::Catch2WithMain +) + +get_target_property(Catch2_INCLUDE_DIR Catch2::Catch2 INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(tests PRIVATE ${Catch2_INCLUDE_DIR}) + +include(Catch) +catch_discover_tests(tests) + +set_target_properties(tests PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin +) \ No newline at end of file From cefd5c6cc88c8aeb635ee6472aa259c15f23043f Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:29:38 +0100 Subject: [PATCH 03/35] Run CI on every PR --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c97fc86..826da4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,12 @@ name: CI on: push: - branches: [main] + branches: + - "**" + - "!main" pull_request: - branches: [main] + branches: + - "**" jobs: build-and-test: From 48eb01e93e4fb60f81c409fe467dda579bfcafa5 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:33:38 +0100 Subject: [PATCH 04/35] Update install step --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 826da4b..069e2ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,10 +17,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Install Dependencies + - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y cmake build-essential llvm-dev libcatch2-dev + sudo add-apt-repository universe + sudo apt-get update + sudo apt-get install -y cmake build-essential libllvm-18-dev llvm-18-dev catch2 - name: Build and Test run: | From 537851bf26755209b8bcce2cc38ab77f84c07375 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:35:14 +0100 Subject: [PATCH 05/35] Update install step --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 069e2ae..8e29861 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,9 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo add-apt-repository universe - sudo apt-get update - sudo apt-get install -y cmake build-essential libllvm-18-dev llvm-18-dev catch2 + sudo apt-get install -y cmake build-essential libcatch2-dev + + sudo apt-get install -y llvm-dev libllvm-s-dev || sudo apt-get install -y llvm-dev - name: Build and Test run: | From 5aacf37ca960d039c6270bf11c24d92dadcefa90 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:36:50 +0100 Subject: [PATCH 06/35] Update install step --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e29861..914eac0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,10 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y cmake build-essential libcatch2-dev - - sudo apt-get install -y llvm-dev libllvm-s-dev || sudo apt-get install -y llvm-dev + sudo apt-get install -y software-properties-common + sudo add-apt-repository universe + sudo apt-get update + sudo apt-get install -y cmake build-essential libcatch2-dev llvm-dev - name: Build and Test run: | From 9e9cec145fdf8af9b212b3319486c9b036952010 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:38:16 +0100 Subject: [PATCH 07/35] Update install step --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 914eac0..63ca378 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y software-properties-common - sudo add-apt-repository universe - sudo apt-get update - sudo apt-get install -y cmake build-essential libcatch2-dev llvm-dev + sudo apt-get install -y cmake build-essential catch2 llvm-dev - name: Build and Test run: | From a959e9002af8222f0fa79c224611e7c943a52250 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:39:11 +0100 Subject: [PATCH 08/35] Downgrade cmake version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08f32f7..64c1a57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 4.4.2) +cmake_minimum_required(VERSION 3.31.6) project(alpha) From e0e7bd87ac701c197bca20258fbca55b9d9ed52d Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:40:51 +0100 Subject: [PATCH 09/35] Include make step --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63ca378..7ba7d61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,4 +25,5 @@ jobs: - name: Build and Test run: | cmake . + make ./build/bin/tests From 50d823eeecaec130afc33a0b294baeea3f6cfb7b Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:43:03 +0100 Subject: [PATCH 10/35] Update import --- src/syntax_analyser/statement/addition/addition.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/syntax_analyser/statement/addition/addition.hpp b/src/syntax_analyser/statement/addition/addition.hpp index e94c873..ef2bcf7 100644 --- a/src/syntax_analyser/statement/addition/addition.hpp +++ b/src/syntax_analyser/statement/addition/addition.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include "syntax_analyser/statement/statement.hpp" #include "syntax_analyser/statement/value/identifier/identifier.hpp" From 5b978f0f07370a28c6dce7e8fe6dfbd1d6d1b453 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:47:11 +0100 Subject: [PATCH 11/35] Update import --- src/syntax_analyser/statement/print/print.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/syntax_analyser/statement/print/print.hpp b/src/syntax_analyser/statement/print/print.hpp index 77944b0..6478fcc 100644 --- a/src/syntax_analyser/statement/print/print.hpp +++ b/src/syntax_analyser/statement/print/print.hpp @@ -1,8 +1,8 @@ #pragma once +#include -#include "syntax_analyser/statement/assignment/assignment_type.hpp" #include "syntax_analyser/statement/statement.hpp" -#include "syntax_analyser/statement/value/identifier/identifier.hpp" +#include "syntax_analyser/statement/value/value.hpp" class PrintStatement : public Statement { public: From 41b6a350a07e81479a89b25981f8653d53696e88 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:22:44 +0100 Subject: [PATCH 12/35] Change to llvm 22 --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ba7d61..caf817e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,13 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y cmake build-essential catch2 llvm-dev + sudo apt-get install -y wget lsb-release software-properties-common gnupg catch2 + + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 22 + + echo "LLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm" >> $GITHUB_ENV - name: Build and Test run: | From 5cc5e94750139bcf16d486858513549fd3a5fd66 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:25:37 +0100 Subject: [PATCH 13/35] Change run path --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index caf817e..b3825c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,15 +21,15 @@ jobs: run: | sudo apt-get update sudo apt-get install -y wget lsb-release software-properties-common gnupg catch2 - + wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 22 - + echo "LLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm" >> $GITHUB_ENV - name: Build and Test run: | cmake . make - ./build/bin/tests + ./bin/tests From 4ec4150fc06b8db6efc651e987ee38bd74d3b753 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 22:12:02 +0100 Subject: [PATCH 14/35] Check for empty buffer --- src/lexer/lexer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index b2d6088..58b057d 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -59,7 +59,7 @@ class Lexer { tokens.addReturn(ReturnToken()); } else if (buffer == "print") { tokens.addPrint(PrintToken()); - } else { + } else if (buffer.size() != 0) { tokens.addIdentifier(IdentifierToken(buffer)); } From 0a3d92dde2975feea21bc5425db118fe9905e4c7 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 22:29:17 +0100 Subject: [PATCH 15/35] Include print documentation --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index f65da79..7caf99d 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,17 @@ uint8 b = a + 1; uint8 c = a + b + 1; ``` +## Printing + +Values can be printed to standard out using a print statement, proceeded by the value wanted to print. + +``` +print 1; + +uint8 a = 2; +print a; +``` + ## Examples Examples can be found in the `/examples` folder. @@ -79,6 +90,7 @@ String segments are converted to a list of tokens. Representing the smallest seg | Identifier | `IDENTIFIER` | Variable identifier | | Number | `NUMBER` | Integer | | Return | `RETURN` | Returns a value from a function | +| Print | `PRINT` | Prints a value | ## Syntax Analyser @@ -90,6 +102,7 @@ Combines tokens into statements. | Assignment | `ASSIGNMENT` | Sets a variable to a value | | Return | `RETURN` | Returns a value from a function | | Addition | `ADDITION` | Adds two values and assigns them to an identifier | +| Print | `PRINT` | Prints the value after it | ## `LLVM` Intermediate Representation From 2aedaf2a92e498db636773c8a27b1e8fe3cdbe25 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Sun, 2 Aug 2026 22:31:01 +0100 Subject: [PATCH 16/35] Change CI to run only pull requests --- .github/workflows/ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3825c7..a9a568b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,6 @@ name: CI on: - push: - branches: - - "**" - - "!main" pull_request: branches: - "**" From 90fb9ddf3cd65a00b9e42de4bb289fdc50c7b97d Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:36:59 +0100 Subject: [PATCH 17/35] Remove unused imports --- src/generation/generator.hpp | 7 ------- src/lexer/lexer.hpp | 1 - 2 files changed, 8 deletions(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index 49e42a4..1668775 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -21,14 +21,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instruction.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Type.h" #include "llvm/IR/Value.h" -#include "llvm/MC/TargetRegistry.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Program.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" #include #include #include diff --git a/src/lexer/lexer.hpp b/src/lexer/lexer.hpp index 58b057d..20c99fb 100644 --- a/src/lexer/lexer.hpp +++ b/src/lexer/lexer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "./string_converter.hpp" From 4fe2296abc2f4b99ae2347f4560d9861e33ce332 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:43:45 +0100 Subject: [PATCH 18/35] Remove optimise step --- src/generation/generator.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index 1668775..8396f17 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -22,6 +22,8 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Value.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/Program.h" #include #include #include @@ -430,13 +432,8 @@ class Generator { std::error_code ec; llvm::raw_fd_ostream dest(filename, ec, llvm::sys::fs::OF_None); - llvm::legacy::PassManager pass; - auto fileType = llvm::CodeGenFileType::ObjectFile; - targetMachine->addPassesToEmitFile(pass, dest, nullptr, fileType); - - pass.run(*module); dest.flush(); llvm::ErrorOr clangPath = From f8030dad7a1fb89b4bdf579f1969164a68b01266 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:48:04 +0100 Subject: [PATCH 19/35] Correctly include omit step --- src/generation/generator.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index 8396f17..db95b86 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -432,8 +433,13 @@ class Generator { std::error_code ec; llvm::raw_fd_ostream dest(filename, ec, llvm::sys::fs::OF_None); + llvm::legacy::PassManager pass; + auto fileType = llvm::CodeGenFileType::ObjectFile; + targetMachine->addPassesToEmitFile(pass, dest, nullptr, fileType); + + pass.run(*module); dest.flush(); llvm::ErrorOr clangPath = From ab1d78b9b9a30316d4e57f112138f95222fed9c7 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:01:10 +0100 Subject: [PATCH 20/35] Create build module method --- src/generation/generator.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index db95b86..a698633 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -56,8 +56,7 @@ class Generator { llvm::InitializeNativeTargetAsmParser(); } - void compile() { - + std::unique_ptr buildModule() { llvm::LLVMContext context; std::unique_ptr module = @@ -408,6 +407,11 @@ class Generator { builder.createReturn(returnValue); } + return std::move(module); + } + + void compile() { + std::unique_ptr module = this->buildModule(); std::cout << "-- LLVM IR --" << std::endl; module->print(llvm::outs(), nullptr); From 3f1560991986351f1fe20f8bb9e2f1b57be0e585 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:01:22 +0100 Subject: [PATCH 21/35] Create template system test --- tests/system.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/system.cpp diff --git a/tests/system.cpp b/tests/system.cpp new file mode 100644 index 0000000..f8dd595 --- /dev/null +++ b/tests/system.cpp @@ -0,0 +1,24 @@ +#include + +#include "generation/generator.hpp" +#include "io/file_reader.hpp" +#include "lexer/lexer.hpp" +#include "lexer/token_container/token_container.hpp" +#include "syntax_analyser/abstract_syntax_tree.hpp" + +TEST_CASE("Run \"./examples/addition.lang\"", "[system]") { + FileReader fileReader("./examples/addition.lang"); + Lexer lexer = Lexer(fileReader.readAll()); + + TokenContainer tokens = lexer.makeTokenList(); + tokens.print(); + + AbstractSyntaxTree ast(tokens); + + Program program = ast.parse(); + program.print(); + + Generator generator(program); + generator.init(); + generator.compile(); +}; From 6042fc0f708275c727b170ed772b2369b9ac0b12 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 22:55:17 +0100 Subject: [PATCH 22/35] Pas context as parameter --- src/generation/generator.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index a698633..a935b7b 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -56,8 +56,7 @@ class Generator { llvm::InitializeNativeTargetAsmParser(); } - std::unique_ptr buildModule() { - llvm::LLVMContext context; + std::unique_ptr buildModule(llvm::LLVMContext& context) { std::unique_ptr module = std::make_unique("build", context); @@ -407,11 +406,13 @@ class Generator { builder.createReturn(returnValue); } - return std::move(module); + return module; } void compile() { - std::unique_ptr module = this->buildModule(); + llvm::LLVMContext context; + std::unique_ptr module = this->buildModule(context); + std::cout << "-- LLVM IR --" << std::endl; module->print(llvm::outs(), nullptr); From cfb7d9f13fc58e86e1cbe5a1c89efdff571e4f01 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 22:55:29 +0100 Subject: [PATCH 23/35] Remove console logs --- src/syntax_analyser/abstract_syntax_tree.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/syntax_analyser/abstract_syntax_tree.cpp b/src/syntax_analyser/abstract_syntax_tree.cpp index afcce01..2341d38 100644 --- a/src/syntax_analyser/abstract_syntax_tree.cpp +++ b/src/syntax_analyser/abstract_syntax_tree.cpp @@ -160,10 +160,8 @@ Program AbstractSyntaxTree::parse() { const Token& token = this->tokenContainer.view(i); buffer.push_back(token); - std::cout << "Reading " << token.tokenType << std::endl; if (token.tokenType == TokenType::END_OF_LINE) { - std::cout << "Reading end of line\n"; if (buffer[0].get().tokenType == TokenType::PRIMITIVE && buffer[1].get().tokenType == TokenType::IDENTIFIER && buffer[2].get().tokenType == TokenType::OPERATOR) { From dc16ead8d466572e8506568965ff1758e4e70e63 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:57:02 +0100 Subject: [PATCH 24/35] Remove print statements --- src/syntax_analyser/abstract_syntax_tree.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/syntax_analyser/abstract_syntax_tree.cpp b/src/syntax_analyser/abstract_syntax_tree.cpp index 2341d38..319ced6 100644 --- a/src/syntax_analyser/abstract_syntax_tree.cpp +++ b/src/syntax_analyser/abstract_syntax_tree.cpp @@ -118,8 +118,6 @@ std::vector> AbstractSyntaxTree::evaluateOperations( const Token& secondToken = static_cast(tokens[tokensIndex + 1].get()); - std::cout << secondToken.tokenType << "\n"; - if (secondToken.tokenType != TokenType::NUMBER && secondToken.tokenType != TokenType::IDENTIFIER) { throw std::runtime_error( @@ -132,9 +130,6 @@ std::vector> AbstractSyntaxTree::evaluateOperations( std::make_unique(outputIdentifier), std::make_unique( (static_cast(secondToken)).value))); - - std::cout << outputIdentifier << " + " - << (static_cast(secondToken)).value << "\n"; } if (secondToken.tokenType == TokenType::IDENTIFIER) { @@ -244,6 +239,5 @@ Program AbstractSyntaxTree::parse() { buffer.clear(); } } - std::cout << "program size: " << program.size() << "\n"; return program; } \ No newline at end of file From 55cf8e2cb7874d5590ce15c74b0f1c7abb4f580c Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:01:40 +0100 Subject: [PATCH 25/35] Seperate print method --- src/generation/generator.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index a935b7b..cc9da1c 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -409,12 +409,13 @@ class Generator { return module; } - void compile() { - llvm::LLVMContext context; - std::unique_ptr module = this->buildModule(context); - + void print_module(std::unique_ptr module) { std::cout << "-- LLVM IR --" << std::endl; module->print(llvm::outs(), nullptr); + } + + void compile(llvm::LLVMContext& context, + std::unique_ptr module) { auto targetTriple = llvm::Triple(llvm::sys::getDefaultTargetTriple()); module->setTargetTriple(targetTriple); From 1a4e067adef633df39b3e59b046582182793ef72 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:01:57 +0100 Subject: [PATCH 26/35] Create system tests on example files --- tests/system.cpp | 81 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/tests/system.cpp b/tests/system.cpp index f8dd595..c0bc778 100644 --- a/tests/system.cpp +++ b/tests/system.cpp @@ -2,23 +2,78 @@ #include "generation/generator.hpp" #include "io/file_reader.hpp" -#include "lexer/lexer.hpp" -#include "lexer/token_container/token_container.hpp" -#include "syntax_analyser/abstract_syntax_tree.hpp" +#include +#include +#include +#include +#include +#include + +class CompilerBuildListener : public Catch::EventListenerBase { +public: + using Catch::EventListenerBase::EventListenerBase; + + void testRunStarting(const Catch::TestRunInfo& testRunInfo) override { + std::cout << "Building compiler\n"; + + int result = std::system("cmake . && make && ./bin/main"); + } +}; + +CATCH_REGISTER_LISTENER(CompilerBuildListener) + +std::string exec(std::string cmd) { + std::array buffer; + std::string result; + + std::unique_ptr pipe(popen(cmd.c_str(), "r"), + pclose); + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} + +void checkOutput(std::string filePath, std::string expectedOut) {} TEST_CASE("Run \"./examples/addition.lang\"", "[system]") { - FileReader fileReader("./examples/addition.lang"); - Lexer lexer = Lexer(fileReader.readAll()); + std::system("./bin/main ./examples/addition.lang"); + int out = std::system("./main.out"); + REQUIRE(out != -1); + REQUIRE(WIFEXITED(out)); + REQUIRE(WEXITSTATUS(out) == 5); +}; + +TEST_CASE("Run \"./examples/integer_primitives.lang\"", "[system]") { + std::system("./bin/main ./examples/integer_primitives.lang"); + int out = std::system("./main.out"); + REQUIRE(out != -1); + REQUIRE(WIFEXITED(out)); + REQUIRE(WEXITSTATUS(out) == 1); +}; - TokenContainer tokens = lexer.makeTokenList(); - tokens.print(); +TEST_CASE("Run \"./examples/print.lang\"", "[system]") { + std::system("./bin/main ./examples/print.lang"); + std::string out = exec("./main.out"); - AbstractSyntaxTree ast(tokens); + REQUIRE(out == "1\n2\n"); +}; + +TEST_CASE("Run \"./examples/transitive_assignment.lang\"", "[system]") { + std::system("./bin/main ./examples/transitive_assignment.lang"); + int out = std::system("./main.out"); + + REQUIRE(out != -1); + REQUIRE(WIFEXITED(out)); + REQUIRE(WEXITSTATUS(out) == 1); +}; - Program program = ast.parse(); - program.print(); +TEST_CASE("Run \"./examples/variable_declaration.lang\"", "[system]") { + std::system("./bin/main ./examples/variable_declaration.lang"); + int out = std::system("./main.out"); - Generator generator(program); - generator.init(); - generator.compile(); + REQUIRE(out != -1); + REQUIRE(WIFEXITED(out)); + REQUIRE(WEXITSTATUS(out) == 1); }; From d64afa0b6d09868a8793cb79062bcbff3c294d70 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:02:10 +0100 Subject: [PATCH 27/35] Include return to show successful run --- examples/integer_primitives.lang | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/integer_primitives.lang b/examples/integer_primitives.lang index cf839ce..7163088 100644 --- a/examples/integer_primitives.lang +++ b/examples/integer_primitives.lang @@ -1,4 +1,6 @@ uint8 a = 255; uint16 b = 65535; uint32 c = 4294967295; -uint64 d = 18446744073709551615; \ No newline at end of file +uint64 d = 18446744073709551615; + +return 1; \ No newline at end of file From 4503fe0b93bd82ba2e7169b706567a2ade7716bc Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:02:19 +0100 Subject: [PATCH 28/35] Create verbose option --- src/main.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8b85e2e..3a6a8e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,13 @@ #include #include +#include #include "./io/file_reader.hpp" #include "./lexer/lexer.hpp" #include "./lexer/token_container/token_container.hpp" #include "generation/generator.hpp" +#include "generation/module.hpp" #include "syntax_analyser/abstract_syntax_tree.hpp" int main(const int argc, char* argv[]) { @@ -17,6 +19,14 @@ int main(const int argc, char* argv[]) { return 1; } + bool verbose = false; + + if (argc == 3) { + if (std::string(argv[2]) == "-v") { + verbose = true; + } + } + FileReader fileReader(argv[1]); if (!fileReader.isOpen()) { std::cerr << "Input file failed to open\n"; @@ -25,14 +35,26 @@ int main(const int argc, char* argv[]) { Lexer lexer(fileReader.readAll()); TokenContainer tokens = lexer.makeTokenList(); - tokens.print(); + if (verbose) { + tokens.print(); + } AbstractSyntaxTree ast(tokens); Program program = ast.parse(); - program.print(); + if (verbose) { + program.print(); + } Generator generator(program); generator.init(); - generator.compile(); + + llvm::LLVMContext context; + std::unique_ptr module = generator.buildModule(context); + + if (verbose) { + generator.print_module(std::move(module)); + } + + generator.compile(context, std::move(module)); } \ No newline at end of file From b14c4126944ef11b4bf821d9e99511f1089e8e4c Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:10:49 +0100 Subject: [PATCH 29/35] Simplify build command --- tests/system.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/system.cpp b/tests/system.cpp index c0bc778..733c7aa 100644 --- a/tests/system.cpp +++ b/tests/system.cpp @@ -6,17 +6,14 @@ #include #include #include +#include #include -#include class CompilerBuildListener : public Catch::EventListenerBase { public: using Catch::EventListenerBase::EventListenerBase; - void testRunStarting(const Catch::TestRunInfo& testRunInfo) override { - std::cout << "Building compiler\n"; - - int result = std::system("cmake . && make && ./bin/main"); + int result = std::system("cmake . && make"); } }; @@ -50,7 +47,7 @@ TEST_CASE("Run \"./examples/integer_primitives.lang\"", "[system]") { int out = std::system("./main.out"); REQUIRE(out != -1); REQUIRE(WIFEXITED(out)); - REQUIRE(WEXITSTATUS(out) == 1); + REQUIRE(WEXITSTATUS(out) == 0); }; TEST_CASE("Run \"./examples/print.lang\"", "[system]") { From 05a45f55469b453e09c4686e208c2e3aa5885836 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:10:54 +0100 Subject: [PATCH 30/35] Remove return --- examples/integer_primitives.lang | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/integer_primitives.lang b/examples/integer_primitives.lang index 7163088..cf839ce 100644 --- a/examples/integer_primitives.lang +++ b/examples/integer_primitives.lang @@ -1,6 +1,4 @@ uint8 a = 255; uint16 b = 65535; uint32 c = 4294967295; -uint64 d = 18446744073709551615; - -return 1; \ No newline at end of file +uint64 d = 18446744073709551615; \ No newline at end of file From 857e5674c0dd6334df827eecd49c5f3b4df4eab5 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:13:23 +0100 Subject: [PATCH 31/35] Remove unused import --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 3a6a8e5..965be31 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,6 @@ #include "./lexer/lexer.hpp" #include "./lexer/token_container/token_container.hpp" #include "generation/generator.hpp" -#include "generation/module.hpp" #include "syntax_analyser/abstract_syntax_tree.hpp" int main(const int argc, char* argv[]) { From 488b307f214f3889cadbbb26cd53f98273e8bdfb Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:17:37 +0100 Subject: [PATCH 32/35] Require compiler --- tests/system.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/system.cpp b/tests/system.cpp index 733c7aa..f739fcf 100644 --- a/tests/system.cpp +++ b/tests/system.cpp @@ -13,7 +13,11 @@ class CompilerBuildListener : public Catch::EventListenerBase { public: using Catch::EventListenerBase::EventListenerBase; void testRunStarting(const Catch::TestRunInfo& testRunInfo) override { - int result = std::system("cmake . && make"); + if (std::filesystem::exists("./bin/main")) { + return; + } + std::cerr << "Compiler not found"; + std::exit(1); } }; From ee16c145d248670754e3f69f2fce851846252351 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:25:31 +0100 Subject: [PATCH 33/35] Include break --- src/generation/generator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index cc9da1c..e595a88 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -358,6 +358,7 @@ class Generator { } builder.store(builder.add(lhs, rhs, outName), outUint.getAlloc()); + break; } case StatementType::PRINT: { const PrintStatement& printStatement = From 99d19d80ac37ca954067d697762721bda4984c1c Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:27:35 +0100 Subject: [PATCH 34/35] Include filesystem --- tests/system.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/system.cpp b/tests/system.cpp index f739fcf..b231b0b 100644 --- a/tests/system.cpp +++ b/tests/system.cpp @@ -8,6 +8,7 @@ #include #include #include +#include class CompilerBuildListener : public Catch::EventListenerBase { public: From 259083f85707b5aec337567de98c687310de6322 Mon Sep 17 00:00:00 2001 From: Thomas <31802793+ThomasNotTom@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:29:35 +0100 Subject: [PATCH 35/35] Compile with PIC --- src/generation/generator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generation/generator.hpp b/src/generation/generator.hpp index e595a88..75c95d8 100644 --- a/src/generation/generator.hpp +++ b/src/generation/generator.hpp @@ -429,7 +429,7 @@ class Generator { auto CPU = "generic"; auto features = ""; llvm::TargetOptions opt; - std::optional RM = std::nullopt; + std::optional RM = llvm::Reloc::PIC_; llvm::TargetMachine* targetMachine = target->createTargetMachine(targetTriple, CPU, features, opt, RM);