execute()

in src/core/function.js [515:746]


  execute(initialStack) {
    const stack = new PostScriptStack(initialStack);
    let counter = 0;
    const operators = this.operators;
    const length = operators.length;
    let operator, a, b;
    while (counter < length) {
      operator = operators[counter++];
      if (typeof operator === "number") {
        // Operator is really an operand and should be pushed to the stack.
        stack.push(operator);
        continue;
      }
      switch (operator) {
        // non standard ps operators
        case "jz": // jump if false
          b = stack.pop();
          a = stack.pop();
          if (!a) {
            counter = b;
          }
          break;
        case "j": // jump
          a = stack.pop();
          counter = a;
          break;

        // all ps operators in alphabetical order (excluding if/ifelse)
        case "abs":
          a = stack.pop();
          stack.push(Math.abs(a));
          break;
        case "add":
          b = stack.pop();
          a = stack.pop();
          stack.push(a + b);
          break;
        case "and":
          b = stack.pop();
          a = stack.pop();
          if (typeof a === "boolean" && typeof b === "boolean") {
            stack.push(a && b);
          } else {
            stack.push(a & b);
          }
          break;
        case "atan":
          b = stack.pop();
          a = stack.pop();
          a = (Math.atan2(a, b) / Math.PI) * 180;
          if (a < 0) {
            a += 360;
          }
          stack.push(a);
          break;
        case "bitshift":
          b = stack.pop();
          a = stack.pop();
          if (a > 0) {
            stack.push(a << b);
          } else {
            stack.push(a >> b);
          }
          break;
        case "ceiling":
          a = stack.pop();
          stack.push(Math.ceil(a));
          break;
        case "copy":
          a = stack.pop();
          stack.copy(a);
          break;
        case "cos":
          a = stack.pop();
          stack.push(Math.cos(((a % 360) / 180) * Math.PI));
          break;
        case "cvi":
          a = stack.pop() | 0;
          stack.push(a);
          break;
        case "cvr":
          // noop
          break;
        case "div":
          b = stack.pop();
          a = stack.pop();
          stack.push(a / b);
          break;
        case "dup":
          stack.copy(1);
          break;
        case "eq":
          b = stack.pop();
          a = stack.pop();
          stack.push(a === b);
          break;
        case "exch":
          stack.roll(2, 1);
          break;
        case "exp":
          b = stack.pop();
          a = stack.pop();
          stack.push(a ** b);
          break;
        case "false":
          stack.push(false);
          break;
        case "floor":
          a = stack.pop();
          stack.push(Math.floor(a));
          break;
        case "ge":
          b = stack.pop();
          a = stack.pop();
          stack.push(a >= b);
          break;
        case "gt":
          b = stack.pop();
          a = stack.pop();
          stack.push(a > b);
          break;
        case "idiv":
          b = stack.pop();
          a = stack.pop();
          stack.push((a / b) | 0);
          break;
        case "index":
          a = stack.pop();
          stack.index(a);
          break;
        case "le":
          b = stack.pop();
          a = stack.pop();
          stack.push(a <= b);
          break;
        case "ln":
          a = stack.pop();
          stack.push(Math.log(a));
          break;
        case "log":
          a = stack.pop();
          stack.push(Math.log10(a));
          break;
        case "lt":
          b = stack.pop();
          a = stack.pop();
          stack.push(a < b);
          break;
        case "mod":
          b = stack.pop();
          a = stack.pop();
          stack.push(a % b);
          break;
        case "mul":
          b = stack.pop();
          a = stack.pop();
          stack.push(a * b);
          break;
        case "ne":
          b = stack.pop();
          a = stack.pop();
          stack.push(a !== b);
          break;
        case "neg":
          a = stack.pop();
          stack.push(-a);
          break;
        case "not":
          a = stack.pop();
          if (typeof a === "boolean") {
            stack.push(!a);
          } else {
            stack.push(~a);
          }
          break;
        case "or":
          b = stack.pop();
          a = stack.pop();
          if (typeof a === "boolean" && typeof b === "boolean") {
            stack.push(a || b);
          } else {
            stack.push(a | b);
          }
          break;
        case "pop":
          stack.pop();
          break;
        case "roll":
          b = stack.pop();
          a = stack.pop();
          stack.roll(a, b);
          break;
        case "round":
          a = stack.pop();
          stack.push(Math.round(a));
          break;
        case "sin":
          a = stack.pop();
          stack.push(Math.sin(((a % 360) / 180) * Math.PI));
          break;
        case "sqrt":
          a = stack.pop();
          stack.push(Math.sqrt(a));
          break;
        case "sub":
          b = stack.pop();
          a = stack.pop();
          stack.push(a - b);
          break;
        case "true":
          stack.push(true);
          break;
        case "truncate":
          a = stack.pop();
          a = a < 0 ? Math.ceil(a) : Math.floor(a);
          stack.push(a);
          break;
        case "xor":
          b = stack.pop();
          a = stack.pop();
          if (typeof a === "boolean" && typeof b === "boolean") {
            stack.push(a !== b);
          } else {
            stack.push(a ^ b);
          }
          break;
        default:
          throw new FormatError(`Unknown operator ${operator}`);
      }
    }
    return stack.stack;
  }