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

@@ -0,0 +1,37 @@
#pragma once
#include <variant>
#include <execute/bytecode.hpp>
#include <execute/error.hpp>
#include <execute/state.hpp>
#include <stdexcept>
#include <vector>
namespace Execute
{
enum class ArgumentType
{
Immediate,
Register,
Memory
};
class ArgumentValue
{
private:
ArgumentType type;
ArgumentType memoryValueType;
std::variant<RegisterByte, int> data;
int & GetRegister(State & state) const;
std::uint8_t * GetMemory(State & state) const;
public:
void Write(int const value, State & state) const;
int Read(State & state) const;
// Returns the size of the argument in bytes
std::size_t Parse(
std::vector<std::uint8_t> const & memory,
std::size_t const pos);
};
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <cstdint>
namespace Execute
{
enum class InstructionByte : std::uint8_t
{
NOOP = 0,
/* Integer functions */
ADD_INTEGER,
SUBTRACT_INTEGER,
DIVIDE_INTEGER,
MULTIPLY_INTEGER,
SHIFT_LEFT_INTEGER,
SHIFT_RIGHT_INTEGER,
SET_INTEGER,
/* Control flow */
JUMP,
INTERRUPT,
CALL,
RETURN,
EXIT,
LESS_THAN_INTEGER,
GREATER_THAN_INTEGER,
EQUALS_INTEGER,
/* Memory */
POP_INTEGER,
PUSH_INTEGER,
/* Values */
IMMEDIATE_INTEGER,
REGISTER,
MEMORY_OP,
LABEL,
};
enum class RegisterByte : std::uint8_t
{
A = 1,
B,
C,
D
};
}

View File

@@ -7,50 +7,44 @@ namespace Execute
{
protected:
std::string message;
std::size_t byteLocation;
public:
std::string const & GetMessage() const;
RuntimeError();
RuntimeError(std::string const & what);
};
class StackUnderflow : public RuntimeError
{
public:
StackUnderflow();
};
class StackOverflow : public RuntimeError
{
public:
StackOverflow();
};
class MissingLabel : public RuntimeError
{
public:
MissingLabel(std::string const & label);
RuntimeError(std::string const & what, std::size_t const byteLocation);
};
class InterruptIndexOutOfRange : public RuntimeError
{
public:
InterruptIndexOutOfRange(int const index);
InterruptIndexOutOfRange(std::size_t const location, int const index);
};
class AttemptedWriteToImmediate : public RuntimeError
{
public:
AttemptedWriteToImmediate(std::size_t const location);
};
class NonExecutableInstruction : public RuntimeError
{
public:
NonExecutableInstruction(std::size_t const location);
};
class NonArgumentByte : public RuntimeError
{
public:
NonArgumentByte(std::size_t const location);
};
class OutOfMemory : public RuntimeError
{
public:
OutOfMemory(int const memoryLocation, int const memorySize);
OutOfMemory(
std::size_t const requiredMemorySize,
std::size_t const actualMemorySize);
};
namespace Internal
{
class BadValueType : public RuntimeError
{
public:
BadValueType();
};
}
}

View File

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

View File

@@ -3,9 +3,10 @@
#include <execute/registers.hpp>
#include <vector>
using InterruptFn = void (*)(Execute::Registers & registers, std::vector<std::uint8_t> & memory);
namespace Execute
{
std::vector<InterruptFn> GetInterrupts();
void ExecuteInterrupt(
int const id,
Execute::Registers & registers,
std::vector<std::uint8_t> & memory);
}

View File

@@ -1,19 +1,14 @@
#pragma once
#include <cstddef>
namespace Execute
{
struct Registers
{
union
{
struct
{
int A;
int B;
int C;
int D;
};
int registers[4];
};
int A, B, C, D;
std::size_t programCounter;
std::size_t stackPointer;
// TODO status registers?
};
}

View File

@@ -1,18 +1,17 @@
#pragma once
#include <execute/interrupts.hpp>
#include <execute/registers.hpp>
#include <string>
#include <unordered_map>
#include <vector>
namespace Execute
{
struct State
{
unsigned currentStatement;
unsigned nextStatement;
std::unordered_map<std::string, unsigned> const * labelStatementIndice;
std::vector<InterruptFn> interrupts;
std::vector<std::uint8_t> memory;
unsigned stackPointer;
bool terminated;
Registers registers;
std::vector<std::uint8_t> memory;
void PushToStack(int const value);
int PopFromStack();
};
}

View File

@@ -1,8 +1,7 @@
#include <configuration.hpp>
#include <execute/flags.hpp>
#include <execute/registers.hpp>
#include <array>
#include <execute/argumentvalue.hpp>
#include <execute/bytecode.hpp>
#include <execute/state.hpp>
#include <interpret/code.hpp>
#include <memory>
namespace Execute
@@ -10,27 +9,39 @@ namespace Execute
class VirtualMachine
{
private:
Flags flags;
Registers registers;
State state;
std::unique_ptr<Interpret::Code const> codePtr;
void DoArithmatic(
InstructionByte const instruction,
std::array<ArgumentValue, 3> & arguments);
void SetInteger(std::array<ArgumentValue, 3> & arguments);
void ExecuteJump(std::array<ArgumentValue, 3> & arguments);
void ExecuteInterrupt(std::array<ArgumentValue, 3> & arguments);
void ExecuteCall(
std::array<ArgumentValue, 3> & arguments,
std::size_t const returnByte);
void ExecuteReturn();
void DoBooleanLogic(
InstructionByte const instruction,
std::array<ArgumentValue, 3> & arguments,
std::size_t const nextInstruction);
void ExecutePop(std::array<ArgumentValue, 3> & arguments);
void ExecutePush(std::array<ArgumentValue, 3> & arguments);
void Step();
public:
void Run();
void SingleStep();
void LoadConfiguration(Configuration const & c);
void LoadCode(std::unique_ptr<Interpret::Code> code);
Flags const & GetFlags() const;
Registers const & GetRegisters() const;
void SetMemorySize(std::size_t const size);
void LoadCode(
std::vector<std::uint8_t> const & byteCode,
bool const printDecodedBytes);
State const & GetState() const;
Interpret::Statement const * const GetCurrentStatement() const;
Execute::InstructionByte GetCurrentInstruction() const;
bool IsTerminated() const;
VirtualMachine();
};
}