136 lines
3.3 KiB
C++
136 lines
3.3 KiB
C++
/*
|
|
* Created by Aaron Helton on 5/28/22.
|
|
*/
|
|
|
|
#include <BFMachine.hpp>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
BFMachine::BFMachine()
|
|
{
|
|
this->memory = new uint8_t[MAX_MEMORY_SIZE];
|
|
this->reset();
|
|
}
|
|
|
|
BFMachine::~BFMachine()
|
|
{
|
|
delete[] memory;
|
|
memory = nullptr;
|
|
}
|
|
|
|
void BFMachine::load(const char *instructions)
|
|
{
|
|
this->program = instructions;
|
|
}
|
|
|
|
void BFMachine::reset()
|
|
{
|
|
memset(this->memory, 0, sizeof(uint8_t)*MAX_MEMORY_SIZE);
|
|
this->dataIndex = 0;
|
|
this->programIndex = 0;
|
|
this->program = nullptr;
|
|
this->error = RETURN_SUCCESS;
|
|
}
|
|
|
|
int BFMachine::execute()
|
|
{
|
|
if(!this->program)
|
|
return RETURN_SUCCESS;
|
|
while(this->error == RETURN_SUCCESS && program[programIndex] != '\0')
|
|
{
|
|
unsigned char command = program[programIndex];
|
|
switch(command)
|
|
{
|
|
case '>': incrementDataPointer(); break;
|
|
case '<': decrementDataPointer(); break;
|
|
case '+': increment(); break;
|
|
case '-': decrement(); break;
|
|
case '.': printByte(); break;
|
|
case ',': readByte(); break;
|
|
case '[':
|
|
if(this->memory[this->dataIndex] == 0)
|
|
{
|
|
uint8_t depth = 1;
|
|
while(this->program[programIndex] != ']' || depth != 0)
|
|
{
|
|
programIndex++;
|
|
if(program[programIndex] == '\0')
|
|
{
|
|
this->error = RETURN_INVALID_INSTRUCTION;
|
|
break;
|
|
}
|
|
if(program[programIndex] == '[')
|
|
depth++;
|
|
if(program[programIndex] == ']')
|
|
depth--;
|
|
}
|
|
}
|
|
break;
|
|
case ']':
|
|
if(this->memory[this->dataIndex] != 0)
|
|
{
|
|
uint8_t depth = 1;
|
|
while(this->program[programIndex] != '[' || depth != 0)
|
|
{
|
|
if(programIndex == 0)
|
|
{
|
|
this->error = RETURN_INVALID_INSTRUCTION;
|
|
break;
|
|
}
|
|
programIndex--;
|
|
if(program[programIndex] == '[')
|
|
depth--;
|
|
if(program[programIndex] == ']')
|
|
depth++;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
programIndex++;
|
|
}
|
|
return this->error;
|
|
}
|
|
|
|
void BFMachine::increment()
|
|
{
|
|
this->memory[this->dataIndex]++;
|
|
}
|
|
|
|
void BFMachine::decrement()
|
|
{
|
|
this->memory[this->dataIndex]--;
|
|
}
|
|
|
|
void BFMachine::incrementDataPointer()
|
|
{
|
|
this->dataIndex++;
|
|
if(this->dataIndex >= MAX_MEMORY_SIZE)
|
|
{
|
|
this->error = RETURN_INVALID_MEMORY_ADDRESS;
|
|
}
|
|
}
|
|
|
|
void BFMachine::decrementDataPointer()
|
|
{
|
|
if(this->dataIndex == 0)
|
|
{
|
|
this->error = RETURN_INVALID_MEMORY_ADDRESS;
|
|
return;
|
|
}
|
|
this->dataIndex--;
|
|
}
|
|
|
|
void BFMachine::printByte()
|
|
{
|
|
auto c = reinterpret_cast<unsigned char>(this->memory[this->dataIndex]);
|
|
std::cout << c;
|
|
}
|
|
|
|
void BFMachine::readByte()
|
|
{
|
|
unsigned char c;
|
|
std::cin >> c;
|
|
this->memory[this->dataIndex] = reinterpret_cast<uint8_t>(c);
|
|
} |