mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-03 17:39:02 +00:00
Refactored how logging works
Made it central reusable logic. No longer needs to be passed around, opened or closed.
This commit is contained in:
@@ -158,7 +158,9 @@
|
||||
<ClInclude Include="LX-Common.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Console.cpp" />
|
||||
<ClCompile Include="src\dllmain.cpp" />
|
||||
<ClCompile Include="src\Logger.cpp" />
|
||||
<ClCompile Include="src\pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
|
||||
@@ -37,5 +37,11 @@
|
||||
<ClCompile Include="src\pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Logger.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Console.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -11,7 +11,8 @@
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#undef NOMINMAX
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
// Else alerts the user that their system is not supported //
|
||||
#else
|
||||
#error "This code is only designed to work on windows"
|
||||
@@ -22,6 +23,17 @@
|
||||
#error "This code is only designed to work with Visual Studio"
|
||||
#endif // _MSC_VER
|
||||
|
||||
// My commonly used macros //
|
||||
|
||||
#define RETURN_IF(condition) if (condition) { return; }
|
||||
#define RETURN_V_IF(value, condition) if (condition) { return value; }
|
||||
|
||||
#ifdef COMMON_EXPORTS
|
||||
#define COMMON_API __declspec(dllexport)
|
||||
#else
|
||||
#define COMMON_API __declspec(dllimport)
|
||||
#endif // COMMON_EXPORTS
|
||||
|
||||
// Includes commonly used STD files //
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace LX
|
||||
{
|
||||
// Enum of colors with their Win32 equivalent value //
|
||||
enum class Color
|
||||
{
|
||||
BLACK = 0,
|
||||
@@ -19,23 +20,11 @@ namespace LX
|
||||
WHITE = 15
|
||||
};
|
||||
|
||||
inline void PrintStringAsColor(const std::string& str, Color c)
|
||||
{
|
||||
// Gets a handle to the console //
|
||||
static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// Sets the color of the console to the desired color //
|
||||
SetConsoleTextAttribute(hConsole, (WORD)c);
|
||||
|
||||
// Outputs the text //
|
||||
std::cout << str;
|
||||
|
||||
// Resets the color //
|
||||
SetConsoleTextAttribute(hConsole, (WORD)Color::LIGHT_GRAY);
|
||||
}
|
||||
// Prints a string to std::cout with a certain color using Win32 API //
|
||||
extern "C" void COMMON_API PrintStringAsColor(const std::string& str, Color c);
|
||||
|
||||
// Util function for getting a line of the source at a given index (used for errors) //
|
||||
inline std::string GetLineAtIndexOf(const std::string src, const std::streamsize index)
|
||||
inline std::string GetLineAtIndexOf(const std::string& src, const std::streamsize index) // <- Has to be inline because of C++ types
|
||||
{
|
||||
// Finds the start of the line //
|
||||
size_t start = src.rfind('\n', index);
|
||||
|
||||
@@ -1,23 +1,51 @@
|
||||
namespace LX
|
||||
{
|
||||
class COMMON_API Log
|
||||
{
|
||||
public:
|
||||
// This class should never be constructed //
|
||||
Log() = delete;
|
||||
|
||||
enum class Format
|
||||
{
|
||||
AUTO,
|
||||
NONE
|
||||
};
|
||||
|
||||
template<Format format = Format::AUTO, typename... Args>
|
||||
static void out(Args... args)
|
||||
{
|
||||
if constexpr (format == Format::AUTO)
|
||||
{
|
||||
((*s_LogFile << ... << args) << "\n");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
(*s_LogFile << ... << args);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void SafeLog(std::ofstream* log, Args... args)
|
||||
static void LogNewSection(Args... args)
|
||||
{
|
||||
if (log != nullptr)
|
||||
{
|
||||
(*log << ... << args);
|
||||
(*log << '\n');
|
||||
}
|
||||
static const char* BREAK = "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-";
|
||||
|
||||
*s_LogFile << '\n' << BREAK << '\n';
|
||||
(*s_LogFile << ... << args);
|
||||
*s_LogFile << '\n' << BREAK << '\n';
|
||||
}
|
||||
|
||||
inline void SafeFlush(std::ofstream* log)
|
||||
{
|
||||
if (log != nullptr)
|
||||
{
|
||||
log->flush();
|
||||
}
|
||||
}
|
||||
private:
|
||||
// Allows ProcAttach to manage the log //
|
||||
friend bool ProcAttach(HMODULE hModule);
|
||||
|
||||
// Gives a standard way to mark a change between different sections within the log output //
|
||||
constexpr const char* LOG_BREAK = "\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";
|
||||
// Initalises the log (Called by DllMain) //
|
||||
static void Init();
|
||||
|
||||
// Closes the log (Called by DllMain) //
|
||||
static void Close();
|
||||
|
||||
static std::ofstream* s_LogFile;
|
||||
};
|
||||
}
|
||||
|
||||
19
Common/src/Console.cpp
Normal file
19
Common/src/Console.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <LX-Common.h>
|
||||
|
||||
namespace LX
|
||||
{
|
||||
void PrintStringAsColor(const std::string& str, Color c)
|
||||
{
|
||||
// Gets a handle to the console //
|
||||
static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// Sets the color of the console to the desired color //
|
||||
SetConsoleTextAttribute(hConsole, (WORD)c);
|
||||
|
||||
// Outputs the text //
|
||||
std::cout << str;
|
||||
|
||||
// Resets the color //
|
||||
SetConsoleTextAttribute(hConsole, (WORD)Color::LIGHT_GRAY);
|
||||
}
|
||||
}
|
||||
26
Common/src/Logger.cpp
Normal file
26
Common/src/Logger.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <LX-Common.h>
|
||||
|
||||
namespace LX
|
||||
{
|
||||
// Allocates memory for the log file pointer //
|
||||
std::ofstream* Log::s_LogFile = nullptr;
|
||||
|
||||
void Log::Init()
|
||||
{
|
||||
// The actual object holding the log file //
|
||||
// Has to be done like this to stop MSVC complaining //
|
||||
static std::ofstream actualLog;
|
||||
|
||||
// Opens the log file and assigns it to the log pointer //
|
||||
actualLog.open("log");
|
||||
s_LogFile = &actualLog;
|
||||
}
|
||||
|
||||
void Log::Close()
|
||||
{
|
||||
// Flushes and closes the log //
|
||||
// Yes I know closing automatically flushes but this function looked empty //
|
||||
s_LogFile->flush();
|
||||
s_LogFile->close();
|
||||
}
|
||||
}
|
||||
@@ -3,36 +3,38 @@
|
||||
|
||||
namespace LX
|
||||
{
|
||||
// All the different functions that can be called by the system //
|
||||
// Currently all empty but here for easier future development //
|
||||
|
||||
using DllFunc = bool(HMODULE);
|
||||
|
||||
static bool ProcAttach(HMODULE hModule)
|
||||
{
|
||||
Log::Init(); // Initalises the log before the main process starts
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ProcDetach(HMODULE hModule)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ThreadAttach(HMODULE hModule)
|
||||
{
|
||||
}
|
||||
|
||||
static bool ThreadDetach(HMODULE hModule)
|
||||
{
|
||||
}
|
||||
static bool ThreadAttach(HMODULE hModule) { return true; }
|
||||
static bool ThreadDetach(HMODULE hModule) { return true; }
|
||||
}
|
||||
|
||||
BOOL __stdcall DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
// All the functions that might be called with their relevant state //
|
||||
static const std::unordered_map<DWORD, LX::DllFunc&> funcs =
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
{ DLL_PROCESS_ATTACH, LX::ProcAttach },
|
||||
{ DLL_PROCESS_DETACH, LX::ProcDetach },
|
||||
{ DLL_THREAD_ATTACH , LX::ThreadAttach },
|
||||
{ DLL_THREAD_DETACH , LX::ThreadDetach }
|
||||
};
|
||||
|
||||
return true;
|
||||
// Returns the output of the relavant function //
|
||||
return funcs.at(ul_reason_for_call)(hModule);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)\$(Configuration)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Parser.lib;Lexer.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Parser.lib;Lexer.lib;Common.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@@ -144,7 +144,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)\$(Configuration)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Parser.lib;Lexer.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Parser.lib;Lexer.lib;Common.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@@ -158,6 +158,11 @@
|
||||
<ClInclude Include="inc\Lexer.h" />
|
||||
<ClInclude Include="inc\Parser.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\Common.vcxproj">
|
||||
<Project>{0abb03b7-e61a-4040-a512-fc05aa35b2a6}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@@ -128,5 +128,5 @@ namespace LX
|
||||
std::string ToString(Token::TokenType t);
|
||||
|
||||
// Lexer function to take in a file and output a vector of tokens //
|
||||
const std::vector<Token> LexicalAnalyze(const std::string& contents, const std::streamsize len, std::ofstream* log);
|
||||
const std::vector<Token> LexicalAnalyze(const std::string& contents, const std::streamsize len);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace LX::AST
|
||||
virtual llvm::Value* GenIR(InfoLLVM& LLVM) = 0;
|
||||
|
||||
// Function to log the node to a file //
|
||||
virtual void Log(std::ofstream* log, unsigned depth) = 0;
|
||||
virtual void Log(unsigned depth) = 0;
|
||||
|
||||
// Function for generating C/C++ code (Currently not implemented) //
|
||||
//virtual void GenC() = 0;
|
||||
@@ -143,7 +143,7 @@ namespace LX
|
||||
};
|
||||
|
||||
// Turns the tokens of a file into it's abstract syntax tree equivalent //
|
||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log);
|
||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens);
|
||||
|
||||
// Turns an abstract binary tree into LLVM intermediate representation //
|
||||
void GenerateIR(FileAST& ast, const std::string& name, const std::filesystem::path& IRPath);
|
||||
|
||||
@@ -33,20 +33,16 @@ namespace LX
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_outPath, const char* a_logPath)
|
||||
extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_outPath)
|
||||
{
|
||||
// Creates the file paths outside of the try-catch so they can be used in errors //
|
||||
std::filesystem::path inpPath;
|
||||
std::filesystem::path outPath;
|
||||
std::filesystem::path logPath;
|
||||
|
||||
// Creates the contents string outside of the try-catch so they can be used in errors //
|
||||
std::string contents;
|
||||
LX::Token::source = &contents;
|
||||
|
||||
// Creates the log-file out of the try-catch so it can be closed propely if an error is thrown //
|
||||
std::unique_ptr<std::ofstream> log = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
// Turns the file paths into the C++ type for handling them //
|
||||
@@ -69,33 +65,22 @@ extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_
|
||||
LX::ThrowIf<LX::InvalidFilePath>(outFile.is_open() == false, "output file path", outPath);
|
||||
outFile.close(); // Opened just to check we can
|
||||
|
||||
// Opens the log file (if there is one specified //
|
||||
if (a_logPath != nullptr)
|
||||
{
|
||||
logPath = a_logPath;
|
||||
log = std::make_unique<std::ofstream>(logPath);
|
||||
LX::ThrowIf<LX::InvalidFilePath>(log->is_open() == false, "log file path", logPath);
|
||||
}
|
||||
|
||||
// Prints the full paths to the console to let the user know compiling is being done //
|
||||
std::cout << std::filesystem::absolute(inpPath) << " -> " << std::filesystem::absolute(outPath) << std::endl;
|
||||
|
||||
// Create tokens out of the input file //
|
||||
LX::InvalidCharInSource::s_Source = &contents;
|
||||
LX::InvalidCharInSource::s_SourceFile = &inpPath;
|
||||
std::vector<LX::Token>tokens = LX::LexicalAnalyze(contents, len, log.get());
|
||||
LX::SafeFlush(log.get());
|
||||
std::vector<LX::Token>tokens = LX::LexicalAnalyze(contents, len);
|
||||
|
||||
// Turns the tokens into an AST //
|
||||
LX::UnexpectedToken::s_Source = &contents;
|
||||
LX::UnexpectedToken::s_SourceFile = &inpPath;
|
||||
|
||||
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens, log.get());
|
||||
LX::SafeFlush(log.get());
|
||||
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens);
|
||||
|
||||
// Turns the AST into LLVM IR //
|
||||
LX::GenerateIR(AST, inpPath.filename().string(), outPath);
|
||||
LX::SafeFlush(log.get());
|
||||
|
||||
// Returns success
|
||||
return 0;
|
||||
@@ -103,9 +88,8 @@ extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_
|
||||
|
||||
catch(LX::RuntimeError& e)
|
||||
{
|
||||
// Closes the log to save everything outputted to it after logging the error //
|
||||
LX::SafeLog(log.get(), LX::LOG_BREAK, "Error thrown of type: ", e.ErrorType(), LX::LOG_BREAK);
|
||||
if (log != nullptr) { log->close(); }
|
||||
// Logs the error. Does not need to close it as it is done after this function returns //
|
||||
LX::Log::LogNewSection("Error thrown of type: ", e.ErrorType());
|
||||
|
||||
// Logs the errors type to the console if built as Debug //
|
||||
#ifdef _DEBUG
|
||||
@@ -122,8 +106,8 @@ extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_
|
||||
// Catches any std errors, there should be none //
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Closes the log if it is open to get as much info as possible //
|
||||
if (log != nullptr) { log->close(); }
|
||||
// Logs the error. Does not need to close it as it is done after this function returns //
|
||||
LX::Log::LogNewSection("std::exception thrown: ", e.what());
|
||||
|
||||
// Prints the std exception to the console //
|
||||
// Any errors here are problems with the code //
|
||||
@@ -134,24 +118,9 @@ extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Catches errors that i was too lazy to code //
|
||||
catch (int)
|
||||
{
|
||||
// Closes the log if it is open to get as much info as possible //
|
||||
if (log != nullptr) { log->close(); }
|
||||
|
||||
std::cout << "An placeholder error occured. Maybe use a language that wasn't coded by a lazy person.\n" << std::endl;
|
||||
|
||||
// Exit code -1 means an undefined error //
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Default catches any non-specified errors //
|
||||
catch (...)
|
||||
{
|
||||
// Closes the log if it is open to get as much info as possible //
|
||||
if (log != nullptr) { log->close(); }
|
||||
|
||||
// Exit code -1 means an undefined error //
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace LX_Build
|
||||
[LibraryImport ("Generator.dll", StringMarshalling = StringMarshalling.Custom,
|
||||
StringMarshallingCustomType = typeof(System.Runtime.InteropServices.Marshalling.AnsiStringMarshaller))]
|
||||
[UnmanagedCallConv(CallConvs = new Type[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
|
||||
public static partial int GenIR(string arg1, string arg2, string? arg3);
|
||||
public static partial int GenIR(string arg1, string arg2);
|
||||
|
||||
// Sets the directory to import the DLLs from //
|
||||
public static void Init()
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace LX_Build
|
||||
LX_API.Init();
|
||||
|
||||
// Generates LLVM IR with the example files //
|
||||
if (LX_API.GenIR("example/main.lx", "example/main.ll", "example/log") != 0)
|
||||
if (LX_API.GenIR("example/main.lx", "example/main.ll") != 0)
|
||||
{
|
||||
// Quits if the IR Generation fails //
|
||||
// The C++ script handles all of the error message outputting //
|
||||
|
||||
@@ -27,8 +27,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LX-Build", "LX-Build\LX-Bui
|
||||
{C88042E2-0E09-4383-93F8-C79F9EE1E897} = {C88042E2-0E09-4383-93F8-C79F9EE1E897}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{4AD62954-631A-4D0F-877E-E1C66E8CEC00}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{0ABB03B7-E61A-4040-A512-FC05AA35B2A6}"
|
||||
EndProject
|
||||
Global
|
||||
@@ -109,7 +107,6 @@ Global
|
||||
{4E4019F5-12E0-4EE2-9658-A0DD3038EEDA} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{D6EAFB31-4AFD-4989-9522-D6609AC4ED64} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{C88042E2-0E09-4383-93F8-C79F9EE1E897} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{0ABB03B7-E61A-4040-A512-FC05AA35B2A6} = {4AD62954-631A-4D0F-877E-E1C66E8CEC00}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {411AFEC9-4075-4FCC-B95A-9288BC822E90}
|
||||
|
||||
@@ -175,10 +175,10 @@ namespace LX
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Token> LX::LexicalAnalyze(const std::string& contents, std::streamsize len, std::ofstream* log)
|
||||
const std::vector<Token> LX::LexicalAnalyze(const std::string& contents, std::streamsize len)
|
||||
{
|
||||
// Logs the start of the lexical analysis
|
||||
SafeLog(log, LOG_BREAK, "Started lexing file", LOG_BREAK);
|
||||
Log::LogNewSection("Lexing file");
|
||||
|
||||
// Allocates a large ammount of memory to hold the output //
|
||||
// Will shrink the size later on to stop excess memory being allocated //
|
||||
@@ -344,11 +344,9 @@ namespace LX
|
||||
|
||||
// Log dumps A LOT of info //
|
||||
|
||||
#ifdef LOG_EVERYTHING
|
||||
|
||||
SafeLog
|
||||
Log::out
|
||||
(
|
||||
log, "Index: ", std::left, std::setw(3), info.index,
|
||||
"Index: ", std::left, std::setw(3), info.index,
|
||||
" Is Alpha: ", info.isAlpha,
|
||||
" Is Numeric: ", info.isNumeric,
|
||||
" In Comment: ", info.inComment,
|
||||
@@ -360,8 +358,6 @@ namespace LX
|
||||
" Current: {", PrintChar(current), "}"
|
||||
);
|
||||
|
||||
#endif // LOG_EVERYTHING
|
||||
|
||||
// Updates trackers to their default state of a new character //
|
||||
|
||||
info.index++;
|
||||
@@ -371,18 +367,13 @@ namespace LX
|
||||
info.wasLastCharNumeric = info.isNumeric;
|
||||
}
|
||||
|
||||
// Logs the tokens if logging is on //
|
||||
if (log != nullptr)
|
||||
{
|
||||
#ifdef LOG_EVERYTHING
|
||||
SafeLog(log, "\n"); // Puts a space when there is a lot in the log
|
||||
#endif // LOG_EVERYTHING
|
||||
Log::out("\n"); // Puts a space to clean up the log
|
||||
|
||||
for (auto& token : tokens)
|
||||
{
|
||||
SafeLog
|
||||
Log::out
|
||||
(
|
||||
log, std::left,
|
||||
std::left,
|
||||
"{ Line: ", std::setw(3), token.line,
|
||||
", Index: ", std::setw(3), token.index,
|
||||
", Length: ", std::setw(2), token.length, " } ",
|
||||
@@ -390,8 +381,7 @@ namespace LX
|
||||
);
|
||||
}
|
||||
|
||||
SafeLog(log, "\n END OF TOKENS");
|
||||
}
|
||||
Log::out("End of tokens");
|
||||
|
||||
// Shrinks the vector down to minimum size before returning to avoid excess memory being allocated
|
||||
tokens.shrink_to_fit();
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file, will throw an error if called on this class //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
// The nodes that are contained within this node //
|
||||
std::vector<std::unique_ptr<Node>> nodes;
|
||||
@@ -48,7 +48,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// The number it stores //
|
||||
@@ -67,7 +67,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// The sides of the operation //
|
||||
@@ -89,7 +89,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// What it is returning (can be null) //
|
||||
@@ -107,7 +107,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// Name of the variable //
|
||||
@@ -127,7 +127,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// Name of the variable //
|
||||
@@ -148,7 +148,7 @@ namespace LX::AST
|
||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
||||
|
||||
// Function to log the node to a file //
|
||||
void Log(std::ofstream* log, unsigned depth) override;
|
||||
void Log(unsigned depth) override;
|
||||
|
||||
private:
|
||||
// The name of the variable //
|
||||
|
||||
@@ -4,61 +4,59 @@
|
||||
|
||||
namespace LX::AST
|
||||
{
|
||||
void MultiNode::Log(std::ofstream* log, unsigned depth)
|
||||
void MultiNode::Log(unsigned depth)
|
||||
{
|
||||
throw int(); // <- TODO: Make an error for this
|
||||
}
|
||||
|
||||
void NumberLiteral::Log(std::ofstream* log, unsigned depth)
|
||||
void NumberLiteral::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
(*log) << "Number: " << m_Number << "\n";
|
||||
Log::out(std::string(depth, '\t'), "Number: ", m_Number);
|
||||
}
|
||||
|
||||
void Operation::Log(std::ofstream* log, unsigned depth)
|
||||
void Operation::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
(*log) << "Operation {" << ToString(m_Operand) << "}:\n";
|
||||
(*log) << std::string(depth + 1, '\t') << "LHS:\n";
|
||||
m_Lhs.get()->Log(log, depth + 2);
|
||||
(*log) << std::string(depth + 1, '\t') << "RHS:\n";
|
||||
m_Rhs.get()->Log(log, depth + 2);
|
||||
Log::out(std::string(depth, '\t'), "Operation {", ToString(m_Operand), "}:");
|
||||
|
||||
Log::out(std::string(depth + 1, '\t'), "LHS:");
|
||||
m_Lhs->Log(depth + 2);
|
||||
|
||||
Log::out(std::string(depth + 1, '\t'), "RHS:");
|
||||
m_Rhs->Log(depth + 2);
|
||||
}
|
||||
|
||||
void ReturnStatement::Log(std::ofstream* log, unsigned depth)
|
||||
void ReturnStatement::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
Log::out<Log::Format::NONE>(std::string(depth, '\t'), "Return");
|
||||
|
||||
if (m_Val == nullptr)
|
||||
if (m_Val != nullptr)
|
||||
{
|
||||
(*log) << "Return\n";
|
||||
Log::out(':');
|
||||
m_Val->Log(depth + 1);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
(*log) << "Return:\n";
|
||||
m_Val->Log(log, depth + 1);
|
||||
Log::out<Log::Format::NONE>('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void VariableDeclaration::Log(std::ofstream* log, unsigned depth)
|
||||
void VariableDeclaration::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
(*log) << "Variable declaration: " << m_Name << "\n";
|
||||
Log::out(std::string(depth, '\t'), "Variable declaration: ", m_Name);
|
||||
}
|
||||
|
||||
void VariableAssignment::Log(std::ofstream* log, unsigned depth)
|
||||
void VariableAssignment::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
(*log) << "Variable assignment:\n";
|
||||
(*log) << std::string(depth + 1, '\t') << "To: " << m_Name << "\n";
|
||||
(*log) << std::string(depth + 1, '\t') << "Value:\n";
|
||||
m_Value.get()->Log(log, depth + 2);
|
||||
Log::out(std::string(depth, '\t'), "Variable assignment:");
|
||||
|
||||
Log::out(std::string(depth + 1, '\t'), "To: ", m_Name);
|
||||
Log::out(std::string(depth + 1, '\t'), "Value:");
|
||||
m_Value->Log(depth + 2);
|
||||
}
|
||||
|
||||
void VariableAccess::Log(std::ofstream* log, unsigned depth)
|
||||
void VariableAccess::Log(unsigned depth)
|
||||
{
|
||||
(*log) << std::string(depth, '\t');
|
||||
(*log) << "Variable: " << m_Name << '\n';
|
||||
Log::out(std::string(depth, '\t'), "Variable: ", m_Name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,16 +29,13 @@ namespace LX
|
||||
struct Parser
|
||||
{
|
||||
// Passes constructor args to members //
|
||||
Parser(std::vector<Token>& _tokens, std::ofstream* _log)
|
||||
: tokens(_tokens), log(_log), index(0), len(_tokens.size()), scopeDepth(0)
|
||||
Parser(std::vector<Token>& _tokens)
|
||||
: tokens(_tokens), index(0), len(_tokens.size()), scopeDepth(0)
|
||||
{}
|
||||
|
||||
// Tokens created by the lexer //
|
||||
std::vector<Token>& tokens;
|
||||
|
||||
// Log to output to (can be null) //
|
||||
std::ofstream* log;
|
||||
|
||||
// Length of the the token vector //
|
||||
const size_t len;
|
||||
|
||||
@@ -203,14 +200,14 @@ namespace LX
|
||||
}
|
||||
|
||||
// Turns the tokens of a file into it's abstract syntax tree equivalent //
|
||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log)
|
||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens)
|
||||
{
|
||||
// Logs the start of the parsing
|
||||
SafeLog(log, LOG_BREAK, "Started parsing tokens", LOG_BREAK);
|
||||
Log::LogNewSection("Started parsing tokens");
|
||||
|
||||
// Creates the output storer and the parser //
|
||||
FileAST output;
|
||||
Parser p(tokens, log);
|
||||
Parser p(tokens);
|
||||
|
||||
// Loops over the tokens and calls the correct parsing function //
|
||||
// Which depends on their type and current state of the parser //
|
||||
@@ -261,7 +258,7 @@ namespace LX
|
||||
for (std::unique_ptr<AST::Node>& containedNode : ((AST::MultiNode*)node.get())->nodes)
|
||||
{
|
||||
// Logs the node to the log //
|
||||
if (log != nullptr) { node->Log(log, 0); }
|
||||
node->Log(0);
|
||||
|
||||
// Adds it to the vector //
|
||||
func.body.push_back(std::move(containedNode));
|
||||
@@ -272,7 +269,7 @@ namespace LX
|
||||
else
|
||||
{
|
||||
// Logs the node to the log //
|
||||
if (log != nullptr) { node->Log(log, 0); }
|
||||
node->Log(0);
|
||||
|
||||
// Adds it to the vector //
|
||||
func.body.push_back(std::move(node));
|
||||
@@ -296,7 +293,7 @@ namespace LX
|
||||
|
||||
// Logs that AST has finished parsing //
|
||||
// TODO: Make this output the AST in a human-readable form //
|
||||
SafeLog(log, "AST length: ", output.functions[0].body.size());
|
||||
Log::out("AST length: ", output.functions[0].body.size());
|
||||
|
||||
// Returns the output and shrinks all uneccesarry allocated memory
|
||||
output.functions.shrink_to_fit();
|
||||
|
||||
@@ -13,12 +13,10 @@ This is my custom compiled language written in C++ based off of the LLVM toolcha
|
||||
- Errors
|
||||
- All simple errors (no members) use the same type
|
||||
- Logging
|
||||
- Less templates
|
||||
- Standard for formatting
|
||||
- Choose what is logged
|
||||
- Choose what is logged (if any)
|
||||
- Refactor
|
||||
- Use dynamic linking for debug builds (faster build times)
|
||||
- General clean up
|
||||
- Parser needs folders
|
||||
- Better .h files
|
||||
|
||||
### Stuff I want to do later (unordered)
|
||||
- I/O manager (Console, Files)
|
||||
|
||||
BIN
example/Main.exe
BIN
example/Main.exe
Binary file not shown.
BIN
example/main.obj
BIN
example/main.obj
Binary file not shown.
Reference in New Issue
Block a user