diff --git a/src/Compiler/ModuleBuilder.cpp b/src/Compiler/ModuleBuilder.cpp index 88b9935..f010d32 100644 --- a/src/Compiler/ModuleBuilder.cpp +++ b/src/Compiler/ModuleBuilder.cpp @@ -10,6 +10,7 @@ #include "Parser/Statement/StatementFunction.h" #include "Parser/Statement/StatementVariable.h" +#include "Parser/Statement/StatementAssignment.h" #include "Parser/Statement/StatementReturn.h" #include "Parser/Statement/StatementExpression.h" #include "Parser/Statement/StatementLoop.h" @@ -44,6 +45,9 @@ void ModuleBuilder::buildStatement(shared_ptr statement) { case StatementKind::VARIABLE: buildVarDeclaration(dynamic_pointer_cast(statement)); break; + case StatementKind::ASSIGNMENT: + buildAssignment(dynamic_pointer_cast(statement)); + break; case StatementKind::BLOCK: buildBlock(dynamic_pointer_cast(statement)); break; @@ -111,6 +115,15 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr statement) builder->CreateStore(value, alloca); } +void ModuleBuilder::buildAssignment(shared_ptr statement) { + llvm::AllocaInst *alloca = allocaMap[statement->getName()]; + if (alloca == nullptr) + failWithMessage("Variable " + statement->getName() + " not defined"); + + llvm::Value *value = valueForExpression(statement->getExpression()); + builder->CreateStore(value, alloca); +} + void ModuleBuilder::buildBlock(shared_ptr statement) { for (shared_ptr &innerStatement : statement->getStatements()) buildStatement(innerStatement); diff --git a/src/Compiler/ModuleBuilder.h b/src/Compiler/ModuleBuilder.h index 7552a5d..2f7b4f8 100644 --- a/src/Compiler/ModuleBuilder.h +++ b/src/Compiler/ModuleBuilder.h @@ -24,6 +24,7 @@ enum class ExpressionBinaryOperation; class Statement; class StatementFunction; class StatementVariable; +class StatementAssignment; class StatementReturn; class StatementExpression; class StatementLoop; @@ -53,6 +54,7 @@ private: void buildStatement(shared_ptr statement); void buildFunctionDeclaration(shared_ptr statement); void buildVarDeclaration(shared_ptr statement); + void buildAssignment(shared_ptr statement); void buildBlock(shared_ptr statement); void buildReturn(shared_ptr statement); void buildLoop(shared_ptr statement); diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 1a7625c..57eb0e2 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -11,6 +11,7 @@ #include "Parser/Statement/StatementFunction.h" #include "Parser/Statement/StatementVariable.h" +#include "Parser/Statement/StatementAssignment.h" #include "Parser/Statement/StatementReturn.h" #include "Parser/Statement/StatementExpression.h" #include "Parser/Statement/StatementMetaExternFunction.h" @@ -51,6 +52,10 @@ shared_ptr Parser::nextStatement() { if (statement != nullptr) return statement; + statement = matchStatementAssignment(); + if (statement != nullptr) + return statement; + statement = matchStatementReturn(); if (statement != nullptr) return statement; @@ -163,6 +168,25 @@ shared_ptr Parser::matchStatementVariable() { return make_shared(identifierToken->getLexme(), valueType, expression); } +shared_ptr Parser::matchStatementAssignment() { + if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::LEFT_ARROW}, true, false)) + return nullptr; + + shared_ptr identifierToken = tokens.at(currentIndex); + currentIndex++; // identifier + currentIndex++; // arrow + + shared_ptr expression = nextExpression(); + if (expression == nullptr || !expression->isValid()) + return matchStatementInvalid("Expected expression"); + + // Expect new line + if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true)) + return matchStatementInvalid("Expected a new line after variable declaration"); + + return make_shared(identifierToken->getLexme(), expression); +} + shared_ptr Parser::matchStatementReturn() { if (!tryMatchingTokenKinds({TokenKind::RETURN}, true, true)) return nullptr; @@ -396,14 +420,14 @@ shared_ptr Parser::matchPrimary() { if (expression != nullptr) return expression; - expression = matchExpressionVariable(); - if (expression != nullptr) - return expression; - expression = matchExpressionCall(); if (expression != nullptr) return expression; + expression = matchExpressionVariable(); + if (expression != nullptr) + return expression; + return nullptr; } diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h index 9a627f5..15efaac 100644 --- a/src/Parser/Parser.h +++ b/src/Parser/Parser.h @@ -21,6 +21,7 @@ private: shared_ptr nextStatement(); shared_ptr matchStatementFunction(); shared_ptr matchStatementVariable(); + shared_ptr matchStatementAssignment(); shared_ptr matchStatementReturn(); shared_ptr matchStatementLoop(); shared_ptr matchStatementExpression(); diff --git a/src/Parser/Statement/Statement.h b/src/Parser/Statement/Statement.h index bee843b..a0b5aa6 100644 --- a/src/Parser/Statement/Statement.h +++ b/src/Parser/Statement/Statement.h @@ -13,6 +13,7 @@ enum class StatementKind { RETURN, FUNCTION, VARIABLE, + ASSIGNMENT, LOOP, META_EXTERN_FUNCTION, INVALID diff --git a/src/Parser/Statement/StatementAssignment.cpp b/src/Parser/Statement/StatementAssignment.cpp new file mode 100644 index 0000000..24fcff6 --- /dev/null +++ b/src/Parser/Statement/StatementAssignment.cpp @@ -0,0 +1,12 @@ +#include "StatementAssignment.h" + +StatementAssignment::StatementAssignment(string name, shared_ptr expression): +Statement(StatementKind::ASSIGNMENT), name(name), expression(expression) { } + +string StatementAssignment::getName() { + return name; +} + +shared_ptr StatementAssignment::getExpression() { + return expression; +} \ No newline at end of file diff --git a/src/Parser/Statement/StatementAssignment.h b/src/Parser/Statement/StatementAssignment.h new file mode 100644 index 0000000..0641e3f --- /dev/null +++ b/src/Parser/Statement/StatementAssignment.h @@ -0,0 +1,14 @@ +#include "Parser/Statement/Statement.h" + +class Expression; + +class StatementAssignment: public Statement { +private: + string name; + shared_ptr expression; + +public: + StatementAssignment(string name, shared_ptr expression); + string getName(); + shared_ptr getExpression(); +}; \ No newline at end of file diff --git a/test.brc b/test.brc index b9cd580..9d31689 100644 --- a/test.brc +++ b/test.brc @@ -1,5 +1,17 @@ -test fun: num1 sint32, num2 sint32 - rep num3 sint32 <- 5, true, num1 < num2 - abc sint32 <- 5 +@extern putchar fun: character sint32 -> sint32 + +stuff fun: num1 sint32, num2 sint32 + ? num1 > num2 + putchar(0x54) + + : + putchar(0x4e) + ; + putchar(0x0a) +; + +main fun -> sint32 + stuff(8, 108) + ret 42 ; \ No newline at end of file