Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
916c169
Create ci file
ThomasNotTom Aug 2, 2026
3148067
Create cmake file
ThomasNotTom Aug 2, 2026
cefd5c6
Run CI on every PR
ThomasNotTom Aug 2, 2026
48eb01e
Update install step
ThomasNotTom Aug 2, 2026
537851b
Update install step
ThomasNotTom Aug 2, 2026
5aacf37
Update install step
ThomasNotTom Aug 2, 2026
9e9cec1
Update install step
ThomasNotTom Aug 2, 2026
a959e90
Downgrade cmake version
ThomasNotTom Aug 2, 2026
e0e7bd8
Include make step
ThomasNotTom Aug 2, 2026
50d823e
Update import
ThomasNotTom Aug 2, 2026
5b978f0
Update import
ThomasNotTom Aug 2, 2026
41b6a35
Change to llvm 22
ThomasNotTom Aug 2, 2026
5cc5e94
Change run path
ThomasNotTom Aug 2, 2026
37bc7c9
Merge pull request #33 from ThomasNotTom/main
ThomasNotTom Aug 2, 2026
323c1f9
Merge pull request #34 from ThomasNotTom/feat/ci-for-tests
ThomasNotTom Aug 2, 2026
4ec4150
Check for empty buffer
ThomasNotTom Aug 2, 2026
a68a015
Merge pull request #36 from ThomasNotTom/fix/lexing-singular-semicolon
ThomasNotTom Aug 2, 2026
0a3d92d
Include print documentation
ThomasNotTom Aug 2, 2026
2aedaf2
Change CI to run only pull requests
ThomasNotTom Aug 2, 2026
7c09817
Merge pull request #38 from ThomasNotTom/documentation/printing
ThomasNotTom Aug 2, 2026
90fb9dd
Remove unused imports
ThomasNotTom Aug 3, 2026
4fe2296
Remove optimise step
ThomasNotTom Aug 3, 2026
f8030da
Correctly include omit step
ThomasNotTom Aug 3, 2026
ab1d78b
Create build module method
ThomasNotTom Aug 3, 2026
3f15609
Create template system test
ThomasNotTom Aug 3, 2026
6042fc0
Pas context as parameter
ThomasNotTom Aug 3, 2026
cfb7d9f
Remove console logs
ThomasNotTom Aug 3, 2026
dc16ead
Remove print statements
ThomasNotTom Aug 3, 2026
55cf8e2
Seperate print method
ThomasNotTom Aug 3, 2026
1a4e067
Create system tests on example files
ThomasNotTom Aug 3, 2026
d64afa0
Include return to show successful run
ThomasNotTom Aug 3, 2026
4503fe0
Create verbose option
ThomasNotTom Aug 3, 2026
b14c412
Simplify build command
ThomasNotTom Aug 3, 2026
05a45f5
Remove return
ThomasNotTom Aug 3, 2026
857e567
Remove unused import
ThomasNotTom Aug 3, 2026
488b307
Require compiler
ThomasNotTom Aug 3, 2026
ee16c14
Include break
ThomasNotTom Aug 3, 2026
99d19d8
Include filesystem
ThomasNotTom Aug 3, 2026
259083f
Compile with PIC
ThomasNotTom Aug 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
pull_request:
branches:
- "**"

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 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
./bin/tests
74 changes: 74 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
cmake_minimum_required(VERSION 3.31.6)

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
)
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand All @@ -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

Expand Down
21 changes: 12 additions & 9 deletions src/generation/generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,16 @@
#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 <iostream>
#include <llvm/CodeGen/TargetPassConfig.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Support/FileSystem.h>
Expand All @@ -60,9 +56,7 @@ class Generator {
llvm::InitializeNativeTargetAsmParser();
}

void compile() {

llvm::LLVMContext context;
std::unique_ptr<llvm::Module> buildModule(llvm::LLVMContext& context) {

std::unique_ptr<llvm::Module> module =
std::make_unique<llvm::Module>("build", context);
Expand Down Expand Up @@ -364,6 +358,7 @@ class Generator {
}

builder.store(builder.add(lhs, rhs, outName), outUint.getAlloc());
break;
}
case StatementType::PRINT: {
const PrintStatement& printStatement =
Expand Down Expand Up @@ -412,8 +407,16 @@ class Generator {
builder.createReturn(returnValue);
}

return module;
}

void print_module(std::unique_ptr<llvm::Module> module) {
std::cout << "-- LLVM IR --" << std::endl;
module->print(llvm::outs(), nullptr);
}

void compile(llvm::LLVMContext& context,
std::unique_ptr<llvm::Module> module) {

auto targetTriple = llvm::Triple(llvm::sys::getDefaultTargetTriple());
module->setTargetTriple(targetTriple);
Expand All @@ -426,7 +429,7 @@ class Generator {
auto CPU = "generic";
auto features = "";
llvm::TargetOptions opt;
std::optional<llvm::Reloc::Model> RM = std::nullopt;
std::optional<llvm::Reloc::Model> RM = llvm::Reloc::PIC_;

llvm::TargetMachine* targetMachine =
target->createTargetMachine(targetTriple, CPU, features, opt, RM);
Expand Down
3 changes: 1 addition & 2 deletions src/lexer/lexer.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <iostream>
#include <string>

#include "./string_converter.hpp"
Expand Down Expand Up @@ -59,7 +58,7 @@ class Lexer {
tokens.addReturn(ReturnToken());
} else if (buffer == "print") {
tokens.addPrint(PrintToken());
} else {
} else if (buffer.size() != 0) {
tokens.addIdentifier(IdentifierToken(buffer));
}

Expand Down
27 changes: 24 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <llvm/Support/raw_ostream.h>

#include <iostream>
#include <memory>

#include "./io/file_reader.hpp"
#include "./lexer/lexer.hpp"
Expand All @@ -17,6 +18,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";
Expand All @@ -25,14 +34,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<llvm::Module> module = generator.buildModule(context);

if (verbose) {
generator.print_module(std::move(module));
}

generator.compile(context, std::move(module));
}
8 changes: 0 additions & 8 deletions src/syntax_analyser/abstract_syntax_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ std::vector<std::unique_ptr<Statement>> AbstractSyntaxTree::evaluateOperations(
const Token& secondToken =
static_cast<const Token&>(tokens[tokensIndex + 1].get());

std::cout << secondToken.tokenType << "\n";

if (secondToken.tokenType != TokenType::NUMBER &&
secondToken.tokenType != TokenType::IDENTIFIER) {
throw std::runtime_error(
Expand All @@ -132,9 +130,6 @@ std::vector<std::unique_ptr<Statement>> AbstractSyntaxTree::evaluateOperations(
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<NumberValue>(
(static_cast<const NumberToken&>(secondToken)).value)));

std::cout << outputIdentifier << " + "
<< (static_cast<const NumberToken&>(secondToken)).value << "\n";
}

if (secondToken.tokenType == TokenType::IDENTIFIER) {
Expand All @@ -160,10 +155,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) {
Expand Down Expand Up @@ -246,6 +239,5 @@ Program AbstractSyntaxTree::parse() {
buffer.clear();
}
}
std::cout << "program size: " << program.size() << "\n";
return program;
}
1 change: 1 addition & 0 deletions src/syntax_analyser/statement/addition/addition.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <memory>

#include "syntax_analyser/statement/statement.hpp"
#include "syntax_analyser/statement/value/identifier/identifier.hpp"
Expand Down
4 changes: 2 additions & 2 deletions src/syntax_analyser/statement/print/print.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include <memory>

#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:
Expand Down
Loading
Loading