views:

158

answers:

0

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?