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.