So, here is my attempt to write a quick and dirty Brainfuck - interpreter:
/// <summary>
/// This the brainfuck interpreter
/// </summary>
internal sealed class BrainfuckInterpreter
{
/// <summary>
/// The "call stack"
/// </summary>
private readonly Stack<int> m_CallStack = new Stack<int>();
/// <summary>
/// The input function
/// </summary>
private readonly Func<byte> m_Input;
/// <summary>
/// The instruction set
/// </summary>
private readonly IDictionary<char, Action> m_InstructionSet =
new Dictionary<char, Action>();
/// <summary>
/// The memory of the program
/// </summary>
private readonly byte[] m_Memory = new byte[32768];
/// <summary>
/// The output function
/// </summary>
private readonly Action<byte> m_Output;
/// <summary>
/// The program code
/// </summary>
private readonly char[] m_Source;
/// <summary>
/// The data pointer
/// </summary>
private int m_DataPointer;
/// <summary>
/// The instruction pointer
/// </summary>
private int m_InstructionPointer;
/// <summary>
/// Constructor
/// </summary>
/// <param name="programCode"></param>
/// <param name="input"></param>
/// <param name="output"></param>
public BrainfuckInterpreter(string programCode, Func<byte> input, Action<byte> output)
{
// Save the program code
this.m_Source = programCode.ToCharArray();
// Store the i/o delegates
this.m_Input = input;
this.m_Output = output;
// Create the instruction set (lol)
this.m_InstructionSet.Add('+', () => this.m_Memory[this.m_DataPointer]++);
this.m_InstructionSet.Add('-', () => this.m_Memory[this.m_DataPointer]--);
this.m_InstructionSet.Add('>', () => this.m_DataPointer++);
this.m_InstructionSet.Add('<', () => this.m_DataPointer--);
this.m_InstructionSet.Add('[', () => this.m_CallStack.Push(this.m_InstructionPointer));
this.m_InstructionSet.Add(
']',
() =>
{
var temp = this.m_CallStack.Pop() - 1;
this.m_InstructionPointer = this.m_Memory[this.m_DataPointer] != 0
? temp
: this.m_InstructionPointer;
});
this.m_InstructionSet.Add('.', () => this.m_Output(this.m_Memory[this.m_DataPointer]));
this.m_InstructionSet.Add(',', () => this.m_Memory[this.m_DataPointer] = this.m_Input());
}
/// <summary>
/// Run the program
/// </summary>
public void Run()
{
// Iterate through the whole program source
while (this.m_InstructionPointer < this.m_Source.Length)
{
// Fetch the next instruction
char instruction = this.m_Source[this.m_InstructionPointer];
// See if that IS an instruction and execute it if so
Action action;
if (this.m_InstructionSet.TryGetValue(instruction, out action))
{
// Yes, it was - execute
action();
}
// Next instruction
this.m_InstructionPointer++;
}
}
}
What would you do different? What could I learn from doing things better / differently?