133 lines
2.9 KiB
C++
133 lines
2.9 KiB
C++
#include <cstdio>
|
|
#include <execute/virtualmachine.hpp>
|
|
#include <fstream>
|
|
#include <interpret/errors.hpp>
|
|
#include <interpret/interpreter.hpp>
|
|
#include <token/tokenizer.hpp>
|
|
|
|
void PrintBadToken(Token::Token const & token, std::vector<std::string> const & lines)
|
|
{
|
|
std::printf("at line number %i, column %i:\n",
|
|
token.lineNumber + 1,
|
|
token.lineColumn + 1);
|
|
std::printf("%s\n", lines[token.lineNumber].c_str());
|
|
for(int i = 0; i < token.lineColumn; ++i)
|
|
{
|
|
std::putc(' ', stdout);
|
|
}
|
|
std::puts("^");
|
|
}
|
|
|
|
void PrintTokenError(Interpret::TokenError const & err, std::vector<std::string> const & lines)
|
|
{
|
|
std::printf("%s ", err.errorMsg.c_str());
|
|
PrintBadToken(err.errorToken, lines);
|
|
}
|
|
|
|
int main(int argc, char ** argv)
|
|
{
|
|
if (argc != 2)
|
|
{
|
|
std::puts("Usage: wassembly [filename.wasm]");
|
|
return 1;
|
|
}
|
|
|
|
std::ifstream input(argv[1]);
|
|
if (!input.is_open())
|
|
{
|
|
std::printf("Error: Cannot open file %s for reading", argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
std::vector<Token::Token> tokens;
|
|
Token::Tokenizer tokenizer;
|
|
std::vector<std::string> lines; // DEBUG
|
|
std::string line;
|
|
unsigned lineNumber = 0;
|
|
while(std::getline(input, line))
|
|
{
|
|
tokenizer.Tokenize(line, lineNumber, tokens);
|
|
++lineNumber;
|
|
lines.push_back(line); // DEBUG
|
|
}
|
|
input.close();
|
|
|
|
// DEBUG
|
|
std::puts("*** Tokenization result ***");
|
|
unsigned statementNumber = 0u;
|
|
std::printf("%02u - ", statementNumber);
|
|
for(unsigned i = 0u; i < tokens.size(); ++i)
|
|
{
|
|
auto const & token = tokens[i];
|
|
token.DebugPrint();
|
|
if (token.type == Token::TokenType::StatementEnd)
|
|
{
|
|
++statementNumber;
|
|
if (i + 1 < tokens.size())
|
|
{
|
|
std::printf("\n%02u - ", statementNumber);
|
|
}
|
|
else
|
|
{
|
|
std::puts("");
|
|
}
|
|
}
|
|
}
|
|
// END DEBUG
|
|
|
|
// Validate the syntax
|
|
bool syntaxOk = true;
|
|
for(auto const & token : tokens)
|
|
{
|
|
if (!token.isValid)
|
|
{
|
|
std::printf("Syntax error ");
|
|
PrintBadToken(token, lines);
|
|
syntaxOk = false;
|
|
}
|
|
}
|
|
|
|
if (!syntaxOk)
|
|
{
|
|
std::puts("Aborting due to syntax error(s)");
|
|
return 1;
|
|
}
|
|
|
|
Interpret::Interpreter interpreter;
|
|
Interpret::Code code;
|
|
try
|
|
{
|
|
interpreter.Interpret(tokens, code);
|
|
}
|
|
catch(Interpret::TokenError & e)
|
|
{
|
|
PrintTokenError(e, lines);
|
|
return 1;
|
|
}
|
|
|
|
// DEBUG
|
|
std::puts("\n*** Labels ***");
|
|
for(auto const & labelIndice : code.labelStatementIndice)
|
|
{
|
|
std::printf("Label %s points to statement %u\n", labelIndice.first.c_str(), labelIndice.second);
|
|
}
|
|
|
|
std::puts("\n*** Execution ***");
|
|
Execute::VirtualMachine vm(code);
|
|
for(unsigned i = 0u; i < 900000; ++i)
|
|
{
|
|
vm.SingleStep();
|
|
auto const & registers = vm.GetRegisters();
|
|
std::printf("A=%i B=%i C=%i D=%i\n", registers.A, registers.B, registers.C, registers.D);
|
|
auto const & flags = vm.GetFlags();
|
|
std::printf("-\n"); // TODO
|
|
auto const & state = vm.GetState();
|
|
std::printf("current_statement=%i\n", state.currentStatement);
|
|
|
|
std::puts("Press any key to step...");
|
|
std::getchar();
|
|
}
|
|
// END DEBUG
|
|
|
|
return 0;
|
|
} |