Compile to bytecode
This commit is contained in:
37
include/execute/argumentvalue.hpp
Normal file
37
include/execute/argumentvalue.hpp
Normal 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);
|
||||
};
|
||||
}
|
||||
43
include/execute/bytecode.hpp
Normal file
43
include/execute/bytecode.hpp
Normal 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
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
struct Flags
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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?
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user