diff --git a/IR-Generator/inc/Parser.h b/IR-Generator/inc/Parser.h index e2bc5b6..f1842bb 100644 --- a/IR-Generator/inc/Parser.h +++ b/IR-Generator/inc/Parser.h @@ -95,6 +95,9 @@ namespace LX // The name of the function // std::string name; + // The parameters of the function // + std::vector params; + // The scope off the function // Scope scope; diff --git a/Lexer/src/Lexer.cpp b/Lexer/src/Lexer.cpp index 357f2e2..4923d32 100644 --- a/Lexer/src/Lexer.cpp +++ b/Lexer/src/Lexer.cpp @@ -8,9 +8,6 @@ namespace LX { - // Helper function for dealing with floating-point number literals // - static constexpr bool CanBePartOfNumberLiteral(const char c) { return (c == '.') || (c == 'f'); } - // Checks if the given word is a keyword before adding it to the tokens // static void TokenizeWord(const std::string& word, std::vector& tokens, LexerInfo& info) { @@ -46,7 +43,7 @@ namespace LX // Works out if the current character is alphabetic or numeric // info.isAlpha = (current >= 'a' && current <= 'z') || (current >= 'A' && current <= 'Z'); - info.isNumeric = (current >= '0' && current <= '9'); + info.isNumeric = (current >= '0' && current <= '9') || (current == '.'); } // Only does next character checks when not at the end // @@ -57,7 +54,7 @@ namespace LX // Sets flags depending on the value of the next character // info.isNextCharAlpha = (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'); - info.isNextCharNumeric = (next >= '0' && next <= '9') || CanBePartOfNumberLiteral(next); + info.isNextCharNumeric = (next >= '0' && next <= '9') || (next == '.'); } // Else defaults the flags to false // @@ -150,7 +147,7 @@ namespace LX } // End of a number // - else if ((info.isNumeric == true || CanBePartOfNumberLiteral(current)) && info.isNextCharNumeric == false && info.lexingNumber == true) + else if (info.isNumeric == true && info.isNextCharNumeric == false && info.lexingNumber == true) { // Pushes the number to the token vector. Number literals are stored as string in the tokens // std::string num(info.source.data() + info.startOfNumberLiteral, (unsigned __int64)(info.index + 1) - info.startOfNumberLiteral); @@ -160,7 +157,7 @@ namespace LX // During a number // else if (info.isNumeric == true); - else if (info.lexingNumber == true && CanBePartOfNumberLiteral(current)); + else if (info.lexingNumber == true); // Start of a word // else if (info.isAlpha == true && info.wasLastCharAlpha == false) diff --git a/Lexer/src/Token.cpp b/Lexer/src/Token.cpp index d342c13..ff2ed3e 100644 --- a/Lexer/src/Token.cpp +++ b/Lexer/src/Token.cpp @@ -37,6 +37,7 @@ namespace LX TOKEN_CASE(Token::CLOSE_PAREN); TOKEN_CASE(Token::ASSIGN); TOKEN_CASE(Token::INT_DEC); + TOKEN_CASE(Token::COMMA); // Default just returns it as it's numerical value // default: return "Unknown: " + std::to_string((int)type); diff --git a/Parser/src/GenIR.cpp b/Parser/src/GenIR.cpp index d4ec4a9..ac55dbe 100644 --- a/Parser/src/GenIR.cpp +++ b/Parser/src/GenIR.cpp @@ -14,16 +14,35 @@ namespace LX return true; } + static llvm::GlobalValue::LinkageTypes GetLinkageType(const std::string& funcName) + { + if (funcName == "main") + { + return llvm::Function::ExternalLinkage; + } + + else + { + return llvm::GlobalValue::InternalLinkage; + } + } + // Generates the LLVM IR for the given function // static void GenerateFunctionIR(FunctionDefinition& funcAST, InfoLLVM& LLVM) { // Creates the functions signature and return type // llvm::FunctionType* retType = llvm::FunctionType::get(llvm::Type::getInt32Ty(LLVM.context), false); // <- Defaults to int currently - llvm::Function* func = llvm::Function::Create(retType, llvm::Function::ExternalLinkage, funcAST.name, LLVM.module); - llvm::BasicBlock* entry = llvm::BasicBlock::Create(LLVM.context, "entry", func); + llvm::Function* func = llvm::Function::Create(retType, GetLinkageType(funcAST.name), funcAST.name, LLVM.module); + llvm::BasicBlock* entry = llvm::BasicBlock::Create(LLVM.context, funcAST.name + "-entry", func); LLVM.builder.SetInsertPoint(entry); + // Adds the function's parameters to the scope // + for (std::string& param : funcAST.params) + { + LLVM.scope->CreateVar(param, LLVM); + } + // Generates the IR within the function by looping over the nodes // for (auto& node : funcAST.body) { diff --git a/Parser/src/Parser.cpp b/Parser/src/Parser.cpp index 1dd0901..3c86f33 100644 --- a/Parser/src/Parser.cpp +++ b/Parser/src/Parser.cpp @@ -185,9 +185,6 @@ namespace LX // Turns the tokens of a file into it's abstract syntax tree equivalent // FileAST TurnTokensIntoAbstractSyntaxTree(std::vector& tokens, const std::filesystem::path& path) { - // Logs the start of the parsing - Log::LogNewSection("Started parsing tokens"); - // Creates the output storer and the parser // FileAST output; ParserInfo p(tokens, path); @@ -198,6 +195,7 @@ namespace LX { switch (p.tokens[p.index].type) { + // Wow this logic needs to be abstracted into a seperate function // case Token::FUNCTION: { // Skips over function token // @@ -211,15 +209,34 @@ namespace LX ThrowIf(p.tokens[p.index].type != Token::IDENTIFIER, Token::IDENTIFIER, p); func.name = p.tokens[p.index++].GetContents(); + // Logs the start of the AST section // + Log::LogNewSection("AST of: ", func.name); + // Checks for opening paren '(' // ThrowIf(p.tokens[p.index].type != Token::OPEN_PAREN, Token::OPEN_PAREN, p); p.index++; - // Loops over all the arguments of the function // - // TODO: Do something with the parameters + // Loops over all the parameters of the function // while (p.index < p.len && (p.tokens[p.index].type == Token::CLOSE_PAREN) == false) { + // Checks for type declaration // + ThrowIf(p.tokens[p.index].type != Token::INT_DEC, Token::INT_DEC, p); p.index++; + + // Checks for variable name // + ThrowIf(p.tokens[p.index].type != Token::IDENTIFIER, Token::IDENTIFIER, p); + std::string pName = p.tokens[p.index].contents; + p.index++; + + // Checks for [comma/close paren] to close the variable declaration // + bool correctEnd = (p.tokens[p.index].type == Token::COMMA) || (p.tokens[p.index].type == Token::CLOSE_PAREN); + ThrowIf(correctEnd == false, Token::UNDEFINED, p.tokens[p.index], "end of parameters", p); + + // Adds the variable to the current scope // + func.params.push_back(pName); + + // Only iterates if not a close paren // + if (p.tokens[p.index].type != Token::CLOSE_PAREN) { p.index++; } } // Skips over close bracket // diff --git a/example/main.lx b/example/main.lx index b2e1b8d..c0cd289 100644 --- a/example/main.lx +++ b/example/main.lx @@ -1,3 +1,8 @@ +func add(int a, int b) +{ + return a + b +} + func main() { int a