text: import { Instruction, INUMBER, IOP1, IOP2, IOP3, IVAR, IVARNAME, IEXPR, IMEMBER, IARRAY } from './instruction.js';
  
  export default function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) {
    var nstack = [];
    var newexpression = [];
    var n1, n2, n3;
    var f;
    for (var i = 0; i < tokens.length; i++) {
      var item = tokens[i];
      var type = item.type;
      if (type === INUMBER || type === IVARNAME) {
        if (Array.isArray(item.value)) {
          nstack.push.apply(
            nstack,
            simplify(
              item.value
                .map(function (x) {
                  return new Instruction(INUMBER, x);
                })
                .concat(new Instruction(IARRAY, item.value.length)),
              unaryOps,
              binaryOps,
              ternaryOps,
              values
            )
          );
        } else {
          nstack.push(item);
        }
      } else if (type === IVAR && values.hasOwnProperty(item.value)) {
        item = new Instruction(INUMBER, values[item.value]);
        nstack.push(item);
      } else if (type === IOP2 && nstack.length > 1) {
        n2 = nstack.pop();
        n1 = nstack.pop();
        f = binaryOps[item.value];
        item = new Instruction(INUMBER, f(n1.value, n2.value));
        nstack.push(item);
      } else if (type === IOP3 && nstack.length > 2) {
        n3 = nstack.pop();
        n2 = nstack.pop();
        n1 = nstack.pop();
        if (item.value === '?') {
          nstack.push(n1.value ? n2.value : n3.value);
        } else {
          f = ternaryOps[item.value];
          item = new Instruction(INUMBER, f(n1.value, n2.value, n3.value));
          nstack.push(item);
        }
      } else if (type === IOP1 && nstack.length > 0) {
        n1 = nstack.pop();
        f = unaryOps[item.value];
        item = new Instruction(INUMBER, f(n1.value));
        nstack.push(item);
      } else if (type === IEXPR) {
        while (nstack.length > 0) {
          newexpression.push(nstack.shift());
        }
        newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values)));
      } else if (type === IMEMBER && nstack.length > 0) {
        n1 = nstack.pop();
        nstack.push(new Instruction(INUMBER, n1.value[item.value]));
      } /* else if (type === IARRAY && nstack.length >= item.value) {
        var length = item.value;
        while (length-- > 0) {
          newexpression.push(nstack.pop());
        }
        newexpression.push(new Instruction(IARRAY, item.value));
      } */ else {
        while (nstack.length > 0) {
          newexpression.push(nstack.shift());
        }
        newexpression.push(item);
      }
    }
    while (nstack.length > 0) {
      newexpression.push(nstack.shift());
    }
    return newexpression;
  }
  