title: How to make a fully functional brainf*ck interpreter?
body: <p>I have tried to implement a BF interpreter in Javascript. It works for many programs like printing <code>Hello world</code>, looping, etc.</p>
  <p>Here is link to a sample interpreter that I use for comparing outputs: <a href="https://sange.fi/esoteric/brainfuck/impl/interp/i.html" rel="nofollow noreferrer">https://sange.fi/esoteric/brainfuck/impl/interp/i.html</a></p>
  <p>But when I try to run a <code>BF to C</code> program, it gets stuck like it is in an infinite loop. It however does work in the sample interpreter above. What am I doing wrong?</p>
  <p>Here is a <code>BF</code> code that converts an input <code>BF</code> code to <code>C</code>.</p>
  <pre><code>+++[&gt;+++++&lt;-]&gt;&gt;+&lt;[&gt;&gt;++++&gt;++&gt;+++++&gt;+++++&gt;+&gt;&gt;+&lt;++[++&lt;]&gt;---]
  
  &gt;++++.&gt;&gt;&gt;.+++++.&gt;------.&lt;--.+++++++++.&gt;+.+.&lt;&lt;&lt;&lt;---.[&gt;]&lt;&lt;.&lt;&lt;&lt;.-------.&gt;++++.
  &lt;+++++.+.&gt;-----.&gt;+.&lt;++++.&gt;&gt;++.&gt;-----.
  
  &lt;&lt;&lt;-----.+++++.-------.&lt;--.&lt;&lt;&lt;.&gt;&gt;&gt;.&lt;&lt;+.&gt;------.-..--.+++.-----&lt;++.&lt;--[&gt;+&lt;-]
  &gt;&gt;&gt;&gt;&gt;--.--.&lt;++++.&gt;&gt;-.&lt;&lt;&lt;.&gt;&gt;&gt;--.&gt;.
  
  &lt;&lt;&lt;&lt;-----.&gt;----.++++++++.----&lt;+.+++++++++&gt;&gt;--.+.++&lt;&lt;&lt;&lt;.[&gt;]&lt;.&gt;&gt;
  
  ,[&gt;&gt;+++[&lt;+++++++&gt;-]&lt;[&lt;[-[-&lt;]]&gt;&gt;[&gt;]&lt;-]&lt;[&lt;+++++&gt;-[&lt;+++&gt;-[&lt;--&gt;-[&lt;+++&gt;-
  [&lt;++++[&gt;[-&gt;&gt;]&lt;[&gt;&gt;]&lt;&lt;-]&gt;[&lt;+++&gt;-[&lt;---&gt;-[&lt;++++&gt;-[&lt;+++[&gt;[-[-[-[-&gt;&gt;]]]]&lt;[&gt;&gt;]&lt;&lt;-]
  &gt;[&lt;+&gt;-[&lt;-&gt;-[&lt;++&gt;-[&lt;[-]&gt;-]]]]]]]]]]]]]
  
  &lt;[
      -[-[&gt;+&lt;-]&gt;]
      &lt;[&lt;&lt;&lt;&lt;.&gt;+++.+.+++.-------.&gt;---.++.&lt;.&gt;-.++&lt;&lt;&lt;&lt;.[&gt;]&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;]
      &lt;[[&lt;]&gt;++.--[&gt;]&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;]
      &lt;[&lt;&lt;++..--&gt;&gt;&gt;&gt;&gt;&gt;]
      &lt;[&lt;&lt;..&gt;&gt;&gt;&gt;&gt;]
      &lt;[&lt;&lt;..-.+&gt;&gt;&gt;&gt;]
      &lt;[&lt;&lt;++..---.+&gt;&gt;&gt;]
      &lt;[&lt;&lt;&lt;.&gt;&gt;.&gt;&gt;&gt;&gt;&gt;]
      &lt;[&lt;&lt;&lt;&lt;-----.+++++&gt;.----.+++.+&gt;---.&lt;&lt;&lt;-.[&gt;]&gt;]
      &lt;[&lt;&lt;&lt;&lt;.-----.&gt;++++.&lt;++.+++&gt;----.&gt;---.&lt;&lt;&lt;.-[&gt;]]
      &lt;[&lt;&lt;&lt;&lt;&lt;----.&gt;&gt;.&lt;&lt;.+++++.&gt;&gt;&gt;+.++&gt;.&gt;&gt;]
      &lt;.&gt;
  ]&gt;
  ,]
  
  &lt;&lt;&lt;&lt;&lt;.&lt;+.&gt;++++.&lt;----.&gt;&gt;---.&lt;&lt;&lt;-.&gt;&gt;&gt;+.&gt;.&gt;.[&lt;]&gt;++.[&gt;]&lt;.
  </code></pre>
  <p>Here is my implementation:</p>
  <pre><code>class Node {
      constructor() {
          this.value = 0;
          this.next = null;
          this.prev = null;
      }
  
      increment() {
          this.value++;
      }
  
      decrement() {
          this.value--;
      }
  }
  
  
  class Memory {
    constructor() {
      this.current = new Node();
      this.outputBuffer = [];
    }
  
    moveRight() {
      if (this.current.next === null) {
          const rightNode = new Node();
          rightNode.prev = this.current
        this.current.next = rightNode;
      }
      this.current = this.current.next;
    }
  
    moveLeft() {
      if (this.current.prev === null) {
          const leftNode = new Node()
          leftNode.next = this.current;
        this.current.prev = leftNode;
      }
      this.current = this.current.prev;
    }
  
    increment() {
      this.current.increment();
    }
  
    decrement() {
      this.current.decrement();
    }
  
    print() {
      this.outputBuffer.push(String.fromCharCode(this.current.value));
    }
  
    input(ch) {
      this.current.value = ch.charCodeAt(0);
    }
  }
  
  class Interpreter {
    reset() {
      this.memory = new Memory();
      this.instructionPointer = 0;
      this.inputPointer = 0;
        this.openingToClosingBrackets = new Map();
        this.closingToOpeningBrackets = new Map();
    }
  
    interpret(code, input = &quot;&quot;) {
      this.reset();
      this.code = code;
      this.matchSquareBrackets();
      this.input = input;
  
      while (!this.reachedEOF()) {
        const instruction = this.code[this.instructionPointer];
  
        switch (instruction) {
          case &quot;+&quot;: this.memory.increment(); break;
          case &quot;-&quot;: this.memory.decrement(); break;
          case &quot;&gt;&quot;: this.memory.moveRight(); break;
          case &quot;&lt;&quot;: this.memory.moveLeft(); break;
          case &quot;.&quot;: this.memory.print(); break;
          case &quot;,&quot;: this.memory.input(this.getNextCharacter()); break;
          case &quot;[&quot;: this.loopStart(); break;
          case &quot;]&quot;: this.loopEnd(); break;
        }
        this.instructionPointer++;
      }
      return this.memory.outputBuffer.join(&quot;&quot;);
    }
  
    reachedEOF() {
      return this.instructionPointer &gt;= this.code.length;
    }
  
    getNextCharacter() {
      if (this.inputPointer &gt;= this.input.length) {
        throw new Error(&quot;EOF. Expected more input characters.&quot;);
      }
      return this.input[this.inputPointer];
    }
  
    loopStart() {
      if (this.memory.current.value !== 0) {
        return;
      }
      this.instructionPointer = this.openingToClosingBrackets.get(
        this.instructionPointer
      );
    }
  
    loopEnd() {
      if (this.memory.current.value === 0) {
          return;
        }
        this.instructionPointer = this.closingToOpeningBrackets.get(
            this.instructionPointer
        );
    }
  
    matchSquareBrackets() {
      const openingStack = [];
      for (let i = 0; i &lt; this.code.length; i++) {
        const ch = this.code[i];
        if (ch === &quot;[&quot;) {
          openingStack.push(i);
        }
        if (ch === &quot;]&quot;) {
          if (openingStack.length === 0) {
            throw new Error(&quot;No matching '[' for ']' at index: &quot; + i);
          }
          const openingMatch = openingStack.pop();
          this.openingToClosingBrackets.set(openingMatch, i);
          this.closingToOpeningBrackets.set(i, openingMatch);
        }
      }
      if (openingStack.length &gt; 0) {
        throw new Error(
          &quot;No matching ']' for '[' at indices: &quot; + openingStack.join(&quot;, &quot;)
        );
      }
    }
  }
  </code></pre>