diff --git a/exercises/forth/.meta/tests.toml b/exercises/forth/.meta/tests.toml index 668537b6ad..68d39fc6ae 100644 --- a/exercises/forth/.meta/tests.toml +++ b/exercises/forth/.meta/tests.toml @@ -109,10 +109,10 @@ "588de2f0-c56e-4c68-be0b-0bb1e603c500" = true # can use different words with the same name -"ac12aaaf-26c6-4a10-8b3c-1c958fa2914c" = false +"ac12aaaf-26c6-4a10-8b3c-1c958fa2914c" = true # can define word that uses word with the same name -"53f82ef0-2750-4ccb-ac04-5d8c1aefabb1" = false +"53f82ef0-2750-4ccb-ac04-5d8c1aefabb1" = true # cannot redefine numbers "35958cee-a976-4a0f-9378-f678518fa322" = true diff --git a/exercises/forth/example.js b/exercises/forth/example.js index 83c8835e18..7557f2acbb 100644 --- a/exercises/forth/example.js +++ b/exercises/forth/example.js @@ -47,9 +47,21 @@ export class Forth { throw new Error('Invalid definition'); } + let execute; + + // Evaluate subprogram immediately if possible, otherwise evaluate later + try { + const stackSize = this.stack.length; + this.evaluate(subprogram); + const result = this.stack.splice(stackSize); + execute = () => result; + } catch { + execute = this.evaluate.bind(this, subprogram); + } + this.commands[word] = { arity: 0, // handled inside the call - execute: this.evaluate.bind(this, subprogram), + execute, }; } diff --git a/exercises/forth/forth.spec.js b/exercises/forth/forth.spec.js index cf45c97eee..cd3f63a633 100644 --- a/exercises/forth/forth.spec.js +++ b/exercises/forth/forth.spec.js @@ -234,6 +234,21 @@ describe('Forth', () => { expect(forth.stack).toEqual([12]); }); + xtest('can use different words with the same name', () => { + forth.evaluate(': foo 5 ;'); + forth.evaluate(': bar foo ;'); + forth.evaluate(': foo 6 ;'); + forth.evaluate('bar foo'); + expect(forth.stack).toEqual([5, 6]); + }); + + xtest('can define word that uses word with the same name', () => { + forth.evaluate(': foo 10 ;'); + forth.evaluate(': foo foo 1 + ;'); + forth.evaluate('foo'); + expect(forth.stack).toEqual([11]); + }); + xtest('cannot redefine numbers', () => { expect(() => { forth.evaluate(': 1 2 ;');