Basic arithmetic and jump labels

This commit is contained in:
2019-11-17 21:02:35 +01:00
commit b84557b3e1
34 changed files with 1350 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
#pragma once
namespace Execute
{
struct Flags
{
};
}

View File

@@ -0,0 +1,19 @@
#pragma once
namespace Execute
{
struct Registers
{
union
{
struct
{
int A;
int B;
int C;
int D;
};
int registers[4];
};
};
}

16
include/execute/state.hpp Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
#include <unordered_map>
namespace Execute
{
struct State
{
unsigned currentStatement;
unsigned nextStatement;
std::unordered_map<std::string, unsigned> const & labelStatementIndice;
State(std::unordered_map<std::string, unsigned> const & labelStatementIndice);
};
}

View File

@@ -0,0 +1,33 @@
#include <execute/flags.hpp>
#include <execute/registers.hpp>
#include <execute/state.hpp>
#include <interpret/code.hpp>
namespace Execute
{
class VirtualMachine
{
private:
Flags flags;
Registers registers;
State state;
bool terminated;
Interpret::Code const & code;
void Step();
public:
void Run();
void SingleStep();
Flags const & GetFlags() const;
Registers const & GetRegisters() const;
State const & GetState() const;
Interpret::Statement const * const GetCurrentStatement() const;
bool IsTerminated() const;
VirtualMachine(Interpret::Code const & code);
};
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <interpret/statement.hpp>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace Interpret
{
struct Code
{
std::vector<std::unique_ptr<Statement>> statements;
std::unordered_map<std::string, unsigned> labelStatementIndice;
};
}

View File

@@ -0,0 +1,62 @@
#pragma once
#include <exception>
#include <string>
#include <token/token.hpp>
namespace Interpret
{
struct TokenError : public std::exception
{
Token::Token errorToken;
std::string errorMsg;
TokenError(Token::Token const & token, std::string const & msg);
};
struct ExpectedArgument : public TokenError
{
ExpectedArgument(Token::Token const & token);
};
struct ExpectedLabel : public TokenError
{
ExpectedLabel(Token::Token const & token);
};
struct ExpectedImmediate : public TokenError
{
ExpectedImmediate(Token::Token const & token);
};
struct ExpectedRegister : public TokenError
{
ExpectedRegister(Token::Token const & token);
};
struct ExpectedOperand : public TokenError
{
ExpectedOperand(Token::Token const & token);
};
struct TooManyArguments : public TokenError
{
TooManyArguments(Token::Token const & token);
};
struct TooFewArguments : public TokenError
{
TooFewArguments(Token::Token const & token);
};
struct MissingEndOfStatment : public TokenError
{
MissingEndOfStatment(Token::Token const & token);
};
namespace Internal
{
struct BadTokenForValue : public TokenError
{
BadTokenForValue(Token::Token const & token);
};
}
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <interpret/code.hpp>
#include <memory>
#include <token/token.hpp>
#include <vector>
namespace Interpret
{
class Interpreter
{
public:
void Interpret(std::vector<Token::Token> const & tokens, Code & code);
};
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <interpret/statement.hpp>
#include <memory>
#include <vector>
namespace Interpret
{
std::unique_ptr<Statement> ExtractStatement(unsigned const operatorIndex, std::vector<Token::Token> const & tokens);
int GetRequiredNumberOfArguments(Token::OperandType const type);
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <execute/flags.hpp>
#include <execute/registers.hpp>
#include <execute/state.hpp>
#include <interpret/value.hpp>
namespace Interpret
{
struct Statement
{
virtual void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) = 0;
};
struct NoArgumentStatement : Statement
{
void (* function)(Execute::Flags & flags, Execute::Registers & registers);
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
};
struct OneArgumentStatement : Statement
{
void (* function)(Execute::Flags & flags, int argument1);
Value firstArgument;
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
};
struct TwoArgumentStatement : Statement
{
void (* function)(Execute::Flags & flags, int argument1, int argument2);
Value firstArgument;
Value secondArgument;
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
};
struct ThreeArgumentStatement : Statement
{
void (* function)(Execute::Flags & flags, int argument1, int argument2, int & argument3);
Value firstArgument;
Value secondArgument;
Value thirdArgument;
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
};
struct JumpStatement : Statement
{
private:
std::string const label;
public:
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
JumpStatement(std::string const & label);
};
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <execute/registers.hpp>
#include <token/token.hpp>
namespace Interpret
{
enum class ValueType
{
Register,
ImmediateInteger
};
struct Value
{
ValueType type;
union
{
int registerIndex;
int integer;
};
int & GetValue(Execute::Registers & registers);
void CreateFromToken(Token::Token const & token);
};
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <string>
namespace Token
{
enum class OperandType
{
Unknown = -1,
AddInteger = 0,
SubtractInteger,
DivideInteger,
MultiplyInteger,
ShiftIntegerLeft,
ShiftIntegerRight,
Jump
};
OperandType GetOperandType(std::string const & op);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
namespace Token
{
enum class RegisterType
{
Unknown = -1,
A = 0,
B,
C,
D
};
RegisterType GetRegisterType(std::string const & reg);
}

27
include/token/token.hpp Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include <token/operandtype.hpp>
#include <token/registertype.hpp>
#include <token/tokentype.hpp>
#include <variant>
namespace Token
{
struct Token
{
int const lineNumber;
int const lineColumn;
TokenType type;
bool isValid;
std::variant<OperandType, RegisterType, int, std::string> data;
Token(int const lineNumber, int const lineColumn);
Token(int const lineNumber, int const lineColumn, OperandType operatorType, bool validness);
Token(int const lineNumber, int const lineColumn, RegisterType registerType, bool validness);
Token(int const lineNumber, int const lineColumn, int value, bool validness);
Token(int const lineNumber, int const lineColumn, std::string const & value, bool validness);
Token(Token const & other);
void DebugPrint() const;
};
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <string>
#include <token/token.hpp>
#include <vector>
namespace Token
{
class Tokenizer
{
public:
void Tokenize(std::string const & line, int const lineNumber, std::vector<Token> & tokens);
};
}

View File

@@ -0,0 +1,14 @@
#pragma once
namespace Token
{
enum class TokenType
{
Unknown = -1,
Operand = 0,
ImmediateInteger,
Register,
StatementEnd,
Label
};
}