Compile to bytecode

This commit is contained in:
2020-09-03 19:03:32 +02:00
parent 473334c3db
commit 96345ad6ba
45 changed files with 1615 additions and 1231 deletions

View File

@@ -1,5 +1,7 @@
#include <compile/compiler.hpp>
#include <compile/errors.hpp>
#include <execute/error.hpp>
#include <fstream>
#include <interpret/errors.hpp>
#include <preprocessor/preprocessor.hpp>
#include <token/errors.hpp>
#include <wassembler.hpp>
@@ -19,18 +21,13 @@ void PrintBadToken(Token::Token const & token, std::vector<std::string> const &
std::puts("^");
}
void PrintTokenError(Interpret::InterpretationError const & err, std::vector<std::string> const & lines)
{
PrintBadToken(err.errorToken, lines);
}
void PrintTokenError(Token::TokenizationError const & err, std::vector<std::string> const & lines)
{
std::printf("%s ", err.errorMsg.c_str());
PrintBadToken(err.errorToken, lines);
}
bool Wassembler::LoadLinesFromFile(std::string const & filePath, std::vector<std::string> & lines) const
bool Wassembler::LoadTextFile(std::string const & filePath, std::vector<std::string> & lines) const
{
std::ifstream input(filePath);
if (!input.is_open())
@@ -48,7 +45,19 @@ bool Wassembler::LoadLinesFromFile(std::string const & filePath, std::vector<std
return true;
}
bool Wassembler::LoadTokens(std::vector<std::string> const & lines, std::vector<Token::Token> & tokens) const
bool Wassembler::Preprocess(std::vector<std::string> & lines) const
{
Preprocessor preprocessor;
preprocessor.process(lines);
if (printSubstitutions)
{
preprocessor.printSubstitutions();
}
return true;
}
bool Wassembler::Tokenize(std::vector<std::string> const & lines, std::vector<Token::Token> & tokens) const
{
Token::Tokenizer tokenizer;
bool tokenizationError = false;
@@ -98,9 +107,64 @@ bool Wassembler::LoadTokens(std::vector<std::string> const & lines, std::vector<
return !(syntaxError || tokenizationError);
}
bool Wassembler::CompileToBytes(
std::vector<Token::Token> const & tokens,
std::vector<std::string> const & lines,
std::vector<std::uint8_t> & bytes) const
{
Compile::Compiler compiler;
try
{
compiler.Compile(tokens, bytes);
}
catch(Compile::CompilationError & e)
{
std::printf("Semantic error ");
PrintBadToken(e.errorToken, lines);
return false;
}
return true;
}
void Wassembler::ExecuteCode(std::vector<uint8_t> const & bytes)
{
vm.LoadCode(bytes, printTranslatedBytes);
// TODO clear memory?
vm.Run();
}
bool Wassembler::CompileFile(
std::string const & filePath,
std::vector<std::uint8_t> & bytes) const
{
std::vector<std::string> lines;
if (!LoadTextFile(filePath, lines))
{
std::printf("Error: Cannot open file %s for reading", filePath.c_str());
return false;
}
if(!Preprocess(lines))
{
std::puts("Aborting due to preprocessor error(s)");
return false;
}
std::vector<Token::Token> tokens;
if (!Tokenize(lines, tokens) || !CompileToBytes(tokens, lines, bytes))
{
std::puts("Aborting due to syntax error(s)");
return false;
}
return true;
}
void Wassembler::SetMemorySize(unsigned const size)
{
config.memorySize = size;
vm.SetMemorySize(size);
}
void Wassembler::EnableSubstitutionsLogging()
@@ -113,50 +177,54 @@ void Wassembler::EnableTokensLogging()
printTokens = true;
}
bool Wassembler::LoadFromFile(std::string const & filePath)
void Wassembler::EnableByteTranslationLogging()
{
printTranslatedBytes = true;
}
bool Wassembler::CompileAndRun(std::string const & filePath)
{
std::vector<std::string> lines;
if (!LoadLinesFromFile(filePath, lines))
std::vector<std::uint8_t> bytes;
if (!CompileFile(filePath, bytes))
{
std::printf("Error: Cannot open file %s for reading", filePath.c_str());
return false;
}
Preprocessor preprocessor;
preprocessor.process(lines);
if (printSubstitutions)
{
preprocessor.printSubstitutions();
}
std::vector<Token::Token> tokens;
if (!LoadTokens(lines, tokens))
{
std::puts("Aborting due to syntax error(s)");
return false;
}
Interpret::Interpreter interpreter;
auto codePtr = std::make_unique<Interpret::Code>();
try
{
interpreter.Interpret(tokens, *codePtr);
ExecuteCode(bytes);
}
catch(Interpret::InterpretationError & e)
catch (Execute::RuntimeError const & e)
{
std::printf("Semantic error ");
PrintBadToken(e.errorToken, lines);
std::puts("Aborting due to semantic error(s)");
std::puts(e.GetMessage().c_str());
std::puts("Aborting due to runtime error(s)");
return false;
}
vm.LoadCode(std::move(codePtr));
vm.LoadConfiguration(config);
return true;
}
void Wassembler::Run()
bool Wassembler::CompileToFile(
std::string const & inputFilePath,
std::string const & outputFilePath)
{
vm.Run();
std::vector<std::uint8_t> bytes;
if (!CompileFile(inputFilePath, bytes))
{
return false;
}
std::ofstream output(outputFilePath, std::ios::binary | std::ios::trunc);
if (!output.is_open())
{
std::printf("Error: Cannot open file %s for writing", outputFilePath.c_str());
return false;
}
for(std::size_t i = 0; i < bytes.size(); ++i)
{
output << bytes[i];
}
return true;
}