const { stdin, stdout } = process;

function Iterator(min, max) {
  let idx = 0;
  return {
    jump(i) { return idx = Math.max(min, Math.min(max, i)) },
    next()  { return this.jump(++idx) },
    prev()  { return this.jump(--idx) },
    over()  { return idx == max },
    curr()  { return idx }
  }
}

function Scanner(text = '') {
  const it = Iterator(0, text.length - 1);
  return Object.assign({}, it, {
    text() {
      return text[ it.curr() ]
    },
    skip(dir) {
      let count = 1;
      while (count) {
        this[dir]();
        let c = this.text();
        if (c == '[') count += (dir == 'next' ? 1 : -1);
        if (c == ']') count += (dir == 'prev' ? 1 : -1);
      }
    }
  })
}

function Tape() {
  const it = Iterator(0, Infinity);
  const cells = [];

  function output(c) {
    stdout.write(String.fromCharCode(c));
  }

  // fix for the broken stdin of nodejs.
  const readStdin = (input => () =>
    new Promise(resolve => {
      if (input.length) {
        resolve(input[0]);
        input = input.substr(1);
      } else {
        stdin.once('data', (chunk) => {
          input = chunk;
          readStdin().then(resolve);
          stdin.pause();
        });
        stdin.setEncoding('utf8');
        stdin.resume();
      }
    })
  )('');

  return Object.assign({}, it, {
    set(n) { cells[ it.curr() ] = (n < 0 ? 0 : n) },
    val() { return cells[ it.curr() ] },
    inc() { this.set((this.val() || 0) + 1) },
    dec() { this.set((this.val() || 0) - 1) },
    put() { output(this.val()) },
    get() {
      return readStdin().then(c => {
        this.set(c.charCodeAt(0));
      });
    }
  });
}

async function interpret(program) {
  const scanner = Scanner(program);
  const tape = Tape();
  while (!scanner.over()) {
    switch (scanner.text()) {
      case '>': tape.next(); break;
      case '<': tape.prev(); break;
      case '+': tape.inc(); break;
      case '-': tape.dec(); break;
      case '.': tape.put(); break;
      case ',': await tape.get(); break;
      case '[': {
        if (!tape.val()) scanner.skip('next');
        break;
      }
      case ']': {
        if (tape.val()) scanner.skip('prev');
        break;
      }
    }
    scanner.next();
  }
}

module.exports = interpret;

@@ -779,78 +779,8 @@
 %5D;%0A%0A
-  function output(c) %7B%0A    stdout.write(String.fromCharCode(c));%0A  %7D%0A%0A
   //
@@ -828,21 +828,16 @@
 nst read
-Stdin
  = (inpu
@@ -927,11 +927,22 @@
 nput
-%5B0%5D
+.charCodeAt(0)
 );%0A 
@@ -1063,29 +1063,24 @@
         read
-Stdin
 ().then(reso
@@ -1301,16 +1301,17 @@
    val()
+ 
  %7B retur
@@ -1343,16 +1343,17 @@
    inc()
+ 
  %7B this.
@@ -1391,16 +1391,17 @@
    dec()
+ 
  %7B this.
@@ -1443,17 +1443,44 @@
 ut()
+ 
  %7B 
-output
+stdout.write(String.fromCharCode
 (thi
@@ -1487,16 +1487,17 @@
 s.val())
+)
  %7D,%0A    
@@ -1501,24 +1501,19 @@
    get()
+ 
  %7B
-%0A     
  return 
@@ -1520,21 +1520,16 @@
 read
-Stdin
 ().then(
 c =%3E
@@ -1528,63 +1528,17 @@
 hen(
-c =%3E %7B%0A        this.set(c.charCodeAt(0));%0A      %7D);%0A   
+this.set)
  %7D%0A 
@@ -1936,23 +1936,8 @@
 %5B': 
-%7B%0A        if (!
 tape
@@ -1934,33 +1934,35 @@
  '%5B': tape.val()
-)
+ %7C%7C
  scanner.skip('n
@@ -1967,39 +1967,23 @@
 'next');
-%0A        break;%0A      %7D
+ break;
 %0A      c
@@ -1995,22 +1995,8 @@
 %5D': 
-%7B%0A        if (
 tape
@@ -2001,17 +2001,19 @@
 pe.val()
-)
+ &&
  scanner
@@ -2030,31 +2030,15 @@
 v');
-%0A        break;%0A      %7D
+ break;
 %0A   

simplify code