I have an issue related to the question about Forth and can't solve it

In question Forth, only two test cases fail with my code, and I can’t solve them.

Here is my code.

export class Forth {
  constructor(stack = []) {
    this.stacks = stack;
    this.obj = {
      "+": () => this.stacks.push(this.stacks.pop() + this.stacks.pop()),
      "-": () => {
        let minus = this.stacks.pop() - this.stacks.pop();
        if (minus) this.stacks.push(-1 * minus);
        else this.stacks.push(0);
      },
      "*": () => this.stacks.push(this.stacks.pop() * this.stacks.pop()),
      "/": () => {
        let first = this.stacks.pop();
        let second = this.stacks.pop();
        if (first !== 0) this.stacks.push(Math.floor(second / first));
        else throw new Error("Division by zero");
      },
      dup: () => {
        if (this.stacks.length == 0) throw new Error("Stack empty");
        this.stacks.push(this.stacks[this.stacks.length - 1]);
      },
      drop: () => {
        if (this.stacks.length == 0) throw new Error("Stack empty");
        this.stacks.pop();
      },
      swap: () => {
        if (this.stack.length < 2) throw new Error("Stack empty");
        let first = this.stacks.pop();
        let second = this.stacks.pop();
        this.stacks.push(first, second);
      },
      over: () => this.stacks.push(this.stacks[this.stacks.length - 2]),
    };
  }

  evaluate(str) {
    str = str.split(" ").map((a) => a.toLowerCase());
    if (str[0] == ":") {
      if (str[1].match(/\d/)) throw new Error("Invalid definition");
      this.obj[str[1]] = () => {
        for (let i = 2; i < str.length - 1; i++) {
          let temp = str[i];
          if (this.obj[temp]) this.obj[temp]();
          else {
            this.stacks.push(Number(temp));
          }
        }
      };
    } else {
      for (let i = 0; i < str.length; i++) {
        console.log("inside check", str[i], this.stacks, this.obj);
        if (i < 2) {
          if (str[i].match(/([\+\-\*\/]|over)$/))
            throw new Error("Stack empty");
        }
        if (this.obj[str[i]]) {
          this.obj[str[i]]();
          console.log("inside if 2", this.stacks);
          continue;
        } else if (str[i].match(/[a-z]/i)) throw new Error("Unknown command");
        this.stacks.push(Number(str[i]));
      }
    }
  }

  get stack() {
    console.log("inside stack", this.stacks);
    return this.stacks;
  }
}

And the failing tests are…?

the first one is

forth.evaluate(': foo 5 ;');
forth.evaluate(': bar foo ;');
forth.evaluate(': foo 6 ;');
forth.evaluate('bar foo');
expect(forth.stack).toEqual([5, 6]);

Error: expect(received).toEqual(expected) // deep equality

  • Expected - 1
  • Received + 1

    Array [

  • 5,
  • 6,
    6,
    ]

and second one is

forth.evaluate(': foo 10 ;');
forth.evaluate(': foo foo 1 + ;');
forth.evaluate('foo');
expect(forth.stack).toEqual([11]);

RangeError: Maximum call stack size exceeded

The way you are defining new words looks wrong. You want to store them as an array of strings to evaluate later. You are currently creating a function that makes assumptions about what str will be at a future time.

By the way str is not a great name to hold an array of strings.

Can you explain me little bit more that what can i do.