Skip to content
Merged
6 changes: 6 additions & 0 deletions examples/subtraction.lang
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
uint8 a = 6 - 1;
uint8 b = a - 1;

uint8 c = a - b;

return c;
4 changes: 4 additions & 0 deletions src/generation/builder/builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class Builder {
return this->irBuilder.CreateAdd(lhs, rhs, name);
};

llvm::Value* subtract(llvm::Value* lhs, llvm::Value* rhs, std::string name) {
return this->irBuilder.CreateSub(lhs, rhs, name);
};

llvm::Value* zext(llvm::Value* in, llvm::Type* outType) {
return this->irBuilder.CreateZExt(in, outType);
};
Expand Down
100 changes: 100 additions & 0 deletions src/generation/generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "syntax_analyser/statement/print/print.hpp"
#include "syntax_analyser/statement/return/return.hpp"
#include "syntax_analyser/statement/statement.hpp"
#include "syntax_analyser/statement/subtraction/subtraction.hpp"
#include "syntax_analyser/statement/value/identifier/identifier.hpp"
#include "syntax_analyser/statement/value/number/number.hpp"
#include "syntax_analyser/statement/value/value.hpp"
Expand Down Expand Up @@ -360,6 +361,105 @@ class Generator {
builder.store(builder.add(lhs, rhs, outName), outUint.getAlloc());
break;
}

case StatementType::SUBTRACTION: {
const SubtractionStatement& subtractionStatement =
static_cast<const SubtractionStatement&>(statement);

std::unique_ptr<BuilderPrimitive>& out =
symbols.at(subtractionStatement.identifier.name);

if (out->getType() != BuilderPrimitiveType::UINT) {
throw std::runtime_error(
"Cannot assign subtraction to non-uint type");
}

BuilderUintPrimitive& outUint =
static_cast<BuilderUintPrimitive&>(*out);

llvm::Value* lhs;
llvm::Value* rhs;

std::string outName = "subtract_";

switch (subtractionStatement.lhs->statementValueType) {
case StatementValueType::IDENTIFIER: {
const IdentifierValue& lhsIdentifierValue =
static_cast<const IdentifierValue&>(
*subtractionStatement.lhs.get());

std::unique_ptr<BuilderPrimitive>& lhsValue =
symbols.at(lhsIdentifierValue.name);

if (lhsValue->getType() != BuilderPrimitiveType::UINT) {
throw std::runtime_error("Cannot subtract non-uint types");
}

BuilderUintPrimitive& lhsUintValue =
static_cast<BuilderUintPrimitive&>(*lhsValue);

lhs = builder.load(lhsUintValue.getLlvmIntegerType(),
lhsUintValue.getAlloc(),
lhsIdentifierValue.name + "_load");

outName += lhsIdentifierValue.name;
break;
}

case StatementValueType::NUMBER: {
const NumberValue& lhsNumberValue =
static_cast<const NumberValue&>(
*subtractionStatement.lhs.get());

lhs = builder.createConst8(lhsNumberValue.value);
outName += "const";
break;
}
}

outName += "_and_";

switch (subtractionStatement.rhs->statementValueType) {
case StatementValueType::IDENTIFIER: {
const IdentifierValue& rhsIdentifierValue =
static_cast<const IdentifierValue&>(
*subtractionStatement.rhs.get());

std::unique_ptr<BuilderPrimitive>& rhsValue =
symbols.at(rhsIdentifierValue.name);

if (rhsValue->getType() != BuilderPrimitiveType::UINT) {
throw std::runtime_error("Cannot subtract non-uint types");
}

BuilderUintPrimitive& rhsValueUint =
static_cast<BuilderUintPrimitive&>(*rhsValue);

rhs = builder.load(rhsValueUint.getLlvmIntegerType(),
rhsValueUint.getAlloc(),
rhsIdentifierValue.name + "_load");

outName += rhsIdentifierValue.name;
break;
}

case StatementValueType::NUMBER: {
const NumberValue& rhsNumberValue =
static_cast<const NumberValue&>(
*subtractionStatement.rhs.get());

rhs = builder.createConst8(rhsNumberValue.value);
outName += "const";

break;
}
}

builder.store(builder.subtract(lhs, rhs, outName),
outUint.getAlloc());
break;
}

case StatementType::PRINT: {
const PrintStatement& printStatement =
static_cast<const PrintStatement&>(statement);
Expand Down
3 changes: 3 additions & 0 deletions src/lexer/lexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "./tokens/primitives/uint64/uint64.hpp"

#include "./tokens/operators/addition/addition.hpp"
#include "lexer/tokens/operators/subtraction/subtraction.hpp"
#include "lexer/tokens/primitives/uint16/uint16.hpp"
#include "lexer/tokens/primitives/uint32/uint32.hpp"
#include "lexer/tokens/print/print.hpp"
Expand Down Expand Up @@ -54,6 +55,8 @@ class Lexer {
tokens.addNumber(StringConverter::toUnsignedLongLong(buffer));
} else if (buffer == "+") {
tokens.addAddition(AdditionToken());
} else if (buffer == "-") {
tokens.addSubtraction(SubtractionToken());
} else if (buffer == "return") {
tokens.addReturn(ReturnToken());
} else if (buffer == "print") {
Expand Down
14 changes: 12 additions & 2 deletions src/lexer/token_container/token_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../tokens/number/number.hpp"
#include "../tokens/operators/operator.hpp"
#include "../tokens/primitives/primitive.hpp"
#include "lexer/tokens/operators/operator_type.hpp"

TokenContainer::TokenContainer() {};

Expand Down Expand Up @@ -59,18 +60,27 @@ void TokenContainer::print() const {

case OPERATOR: {
const OperatorToken& op = static_cast<const OperatorToken&>(token);
std::string out = "OPERATOR(";

switch (op.operatorType) {
case ASSIGNMENT: {
std::cout << "OPERATOR(=)\n";
out += "=";
break;
}

case ADDITION: {
std::cout << "OPERATOR(+)\n";
out += "+";
break;
}

case SUBTRACTION: {
out += "-";
break;
}
}
out += ")";

std::cout << out << "\n";
break;
}

Expand Down
5 changes: 5 additions & 0 deletions src/lexer/token_container/token_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "lexer/tokens/number/number.hpp"
#include "lexer/tokens/operators/addition/addition.hpp"
#include "lexer/tokens/operators/assignment/assignment.hpp"
#include "lexer/tokens/operators/subtraction/subtraction.hpp"
#include "lexer/tokens/primitives/uint16/uint16.hpp"
#include "lexer/tokens/primitives/uint32/uint32.hpp"
#include "lexer/tokens/primitives/uint64/uint64.hpp"
Expand Down Expand Up @@ -39,6 +40,10 @@ class TokenContainer {
tokens.push_back(std::make_unique<AdditionToken>(token));
}

void addSubtraction(const SubtractionToken& token) {
tokens.push_back(std::make_unique<SubtractionToken>(token));
}

void addAssignment(const AssignmentToken& token) {
tokens.push_back(std::make_unique<AssignmentToken>(token));
}
Expand Down
2 changes: 1 addition & 1 deletion src/lexer/tokens/operators/operator_type.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#pragma once

enum OperatorType { ASSIGNMENT = 1, ADDITION = 2 };
enum OperatorType { ASSIGNMENT = 1, ADDITION = 2, SUBTRACTION = 3 };
4 changes: 4 additions & 0 deletions src/lexer/tokens/operators/subtraction/subtraction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "./subtraction.hpp"

SubtractionToken::SubtractionToken()
: OperatorToken(OperatorType::SUBTRACTION) {}
8 changes: 8 additions & 0 deletions src/lexer/tokens/operators/subtraction/subtraction.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include "../operator.hpp"

class SubtractionToken : public OperatorToken {
public:
SubtractionToken();
};
61 changes: 46 additions & 15 deletions src/syntax_analyser/abstract_syntax_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ std::vector<std::unique_ptr<Statement>> AbstractSyntaxTree::evaluateOperations(
const OperatorToken& firstTokenOperator =
static_cast<const OperatorToken&>(firstToken);

if (firstTokenOperator.operatorType != OperatorType::ADDITION) {
throw std::format_error("Only `+` operator is implemented");
if (firstTokenOperator.operatorType != OperatorType::ADDITION &&
firstTokenOperator.operatorType != OperatorType::SUBTRACTION) {
throw std::format_error("Only `+` and `-` operators are implemented");
}

const Token& secondToken =
Expand All @@ -124,20 +125,50 @@ std::vector<std::unique_ptr<Statement>> AbstractSyntaxTree::evaluateOperations(
"Token adjacent to operator must be an identifier or a value");
}

if (secondToken.tokenType == TokenType::NUMBER) {
statements.push_back(std::make_unique<AdditionStatement>(
IdentifierValue(outputIdentifier),
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<NumberValue>(
(static_cast<const NumberToken&>(secondToken)).value)));
}
switch (firstTokenOperator.operatorType) {
case OperatorType::ADDITION: {
if (secondToken.tokenType == TokenType::NUMBER) {
statements.push_back(std::make_unique<AdditionStatement>(
IdentifierValue(outputIdentifier),
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) {
statements.push_back(std::make_unique<AdditionStatement>(
IdentifierValue(outputIdentifier),
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<IdentifierValue>(
static_cast<const IdentifierToken&>(secondToken).name)));
if (secondToken.tokenType == TokenType::IDENTIFIER) {
statements.push_back(std::make_unique<AdditionStatement>(
IdentifierValue(outputIdentifier),
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<IdentifierValue>(
static_cast<const IdentifierToken&>(secondToken).name)));
}

break;
}

case OperatorType::SUBTRACTION: {
if (secondToken.tokenType == TokenType::NUMBER) {
statements.push_back(std::make_unique<SubtractionStatement>(
IdentifierValue(outputIdentifier),
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<NumberValue>(
(static_cast<const NumberToken&>(secondToken)).value)));
}

if (secondToken.tokenType == TokenType::IDENTIFIER) {
statements.push_back(std::make_unique<SubtractionStatement>(
IdentifierValue(outputIdentifier),
std::make_unique<IdentifierValue>(outputIdentifier),
std::make_unique<IdentifierValue>(
static_cast<const IdentifierToken&>(secondToken).name)));
}

break;
}
}

tokensIndex += 2;
Expand Down
20 changes: 20 additions & 0 deletions src/syntax_analyser/program/program.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "syntax_analyser/statement/print/print.hpp"
#include "syntax_analyser/statement/return/return.hpp"
#include "syntax_analyser/statement/statement.hpp"
#include "syntax_analyser/statement/subtraction/subtraction.hpp"
#include "syntax_analyser/statement/value/identifier/identifier.hpp"
#include "syntax_analyser/statement/value/number/number.hpp"
#include "syntax_analyser/statement/value/value.hpp"
Expand Down Expand Up @@ -109,6 +110,15 @@ class Program {
<< rhs << ";\n";
}

void printSubtractionStatement(
const SubtractionStatement& subtractionStatement) const {
std::string lhs = this->getStatementValueString(*subtractionStatement.lhs);
std::string rhs = this->getStatementValueString(*subtractionStatement.rhs);

std::cout << subtractionStatement.identifier.name << " = " << lhs << " - "
<< rhs << ";\n";
}

void printPrintStatement(const PrintStatement& printStatement) const {
std::string value = this->getStatementValueString(*printStatement.value);

Expand Down Expand Up @@ -166,6 +176,16 @@ class Program {
break;
}

case StatementType::SUBTRACTION: {

const SubtractionStatement& subtractionStatement =
static_cast<const SubtractionStatement&>(statement);

this->printSubtractionStatement(subtractionStatement);

break;
}

case StatementType::INITIALISATION: {
const InitialisationStatement& initialisationStatement =
static_cast<const InitialisationStatement&>(statement);
Expand Down
3 changes: 2 additions & 1 deletion src/syntax_analyser/statement/statement_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ enum class StatementType {
ASSIGNMENT = 2,
RETURN = 3,
ADDITION = 4,
PRINT = 5
SUBTRACTION = 5,
PRINT = 6
};
18 changes: 18 additions & 0 deletions src/syntax_analyser/statement/subtraction/subtraction.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#include <memory>

#include "syntax_analyser/statement/statement.hpp"
#include "syntax_analyser/statement/value/identifier/identifier.hpp"

class SubtractionStatement : public Statement {
public:
const IdentifierValue identifier;
const std::unique_ptr<StatementValue> lhs;
const std::unique_ptr<StatementValue> rhs;

SubtractionStatement(const IdentifierValue identifier,
std::unique_ptr<StatementValue> lhs,
std::unique_ptr<StatementValue> rhs)
: Statement(StatementType::SUBTRACTION), identifier(identifier),
lhs(std::move(lhs)), rhs(std::move(rhs)) {};
};
Loading