{ "exercise": "forth", "version": "1.5.0", "comments": [ "The cases are split into multiple sections, all with the same structure.", "In all cases, the `expected` key is the resulting stack", "after executing the Forth program contained in the `input` key." ], "cases": [ { "description": "parsing and numbers", "cases": [ { "description": "numbers just get pushed onto the stack", "property": "evaluate", "input": { "instructions": ["1 2 3 4 5"] }, "expected": [1, 2, 3, 4, 5] } ] }, { "description": "addition", "cases": [ { "description": "can add two numbers", "property": "evaluate", "input": { "instructions": ["1 2 +"] }, "expected": [3] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["+"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 +"] }, "expected": null } ] }, { "description": "subtraction", "cases": [ { "description": "can subtract two numbers", "property": "evaluate", "input": { "instructions": ["3 4 -"] }, "expected": [-1] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["-"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 -"] }, "expected": null } ] }, { "description": "multiplication", "cases": [ { "description": "can multiply two numbers", "property": "evaluate", "input": { "instructions": ["2 4 *"] }, "expected": [8] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["*"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 *"] }, "expected": null } ] }, { "description": "division", "cases": [ { "description": "can divide two numbers", "property": "evaluate", "input": { "instructions": ["12 3 /"] }, "expected": [4] }, { "description": "performs integer division", "property": "evaluate", "input": { "instructions": ["8 3 /"] }, "expected": [2] }, { "description": "errors if dividing by zero", "property": "evaluate", "input": { "instructions": ["4 0 /"] }, "expected": null }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["/"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 /"] }, "expected": null } ] }, { "description": "combined arithmetic", "cases": [ { "description": "addition and subtraction", "property": "evaluate", "input": { "instructions": ["1 2 + 4 -"] }, "expected": [-1] }, { "description": "multiplication and division", "property": "evaluate", "input": { "instructions": ["2 4 * 3 /"] }, "expected": [2] } ] }, { "description": "dup", "cases": [ { "description": "copies a value on the stack", "property": "evaluate", "input": { "instructions": ["1 dup"] }, "expected": [1, 1] }, { "description": "copies the top value on the stack", "property": "evaluate", "input": { "instructions": ["1 2 dup"] }, "expected": [1, 2, 2] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["dup"] }, "expected": null } ] }, { "description": "drop", "cases": [ { "description": "removes the top value on the stack if it is the only one", "property": "evaluate", "input": { "instructions": ["1 drop"] }, "expected": [] }, { "description": "removes the top value on the stack if it is not the only one", "property": "evaluate", "input": { "instructions": ["1 2 drop"] }, "expected": [1] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["drop"] }, "expected": null } ] }, { "description": "swap", "cases": [ { "description": "swaps the top two values on the stack if they are the only ones", "property": "evaluate", "input": { "instructions": ["1 2 swap"] }, "expected": [2, 1] }, { "description": "swaps the top two values on the stack if they are not the only ones", "property": "evaluate", "input": { "instructions": ["1 2 3 swap"] }, "expected": [1, 3, 2] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["swap"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 swap"] }, "expected": null } ] }, { "description": "over", "cases": [ { "description": "copies the second element if there are only two", "property": "evaluate", "input": { "instructions": ["1 2 over"] }, "expected": [1, 2, 1] }, { "description": "copies the second element if there are more than two", "property": "evaluate", "input": { "instructions": ["1 2 3 over"] }, "expected": [1, 2, 3, 2] }, { "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { "instructions": ["over"] }, "expected": null }, { "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { "instructions": ["1 over"] }, "expected": null } ] }, { "description": "user-defined words", "cases": [ { "description": "can consist of built-in words", "property": "evaluate", "input": { "instructions": [ ": dup-twice dup dup ;", "1 dup-twice" ] }, "expected": [1, 1, 1] }, { "description": "execute in the right order", "property": "evaluate", "input": { "instructions": [ ": countup 1 2 3 ;", "countup" ] }, "expected": [1, 2, 3] }, { "description": "can override other user-defined words", "property": "evaluate", "input": { "instructions": [ ": foo dup ;", ": foo dup dup ;", "1 foo" ] }, "expected": [1, 1, 1] }, { "description": "can override built-in words", "property": "evaluate", "input": { "instructions": [ ": swap dup ;", "1 swap" ] }, "expected": [1, 1] }, { "description": "can override built-in operators", "property": "evaluate", "input": { "instructions": [ ": + * ;", "3 4 +" ] }, "expected": [12] }, { "description": "cannot redefine numbers", "property": "evaluate", "input": { "instructions": [": 1 2 ;"] }, "expected": null }, { "description": "errors if executing a non-existent word", "property": "evaluate", "input": { "instructions": ["foo"] }, "expected": null } ] }, { "description": "case-insensitivity", "cases": [ { "description": "DUP is case-insensitive", "property": "evaluate", "input": { "instructions": ["1 DUP Dup dup"] }, "expected": [1, 1, 1, 1] }, { "description": "DROP is case-insensitive", "property": "evaluate", "input": { "instructions": ["1 2 3 4 DROP Drop drop"] }, "expected": [1] }, { "description": "SWAP is case-insensitive", "property": "evaluate", "input": { "instructions": ["1 2 SWAP 3 Swap 4 swap"] }, "expected": [2, 3, 4, 1] }, { "description": "OVER is case-insensitive", "property": "evaluate", "input": { "instructions": ["1 2 OVER Over over"] }, "expected": [1, 2, 1, 2, 1] }, { "description": "user-defined words are case-insensitive", "property": "evaluate", "input": { "instructions": [ ": foo dup ;", "1 FOO Foo foo" ] }, "expected": [1, 1, 1, 1] }, { "description": "definitions are case-insensitive", "property": "evaluate", "input": { "instructions": [ ": SWAP DUP Dup dup ;", "1 swap" ] }, "expected": [1, 1, 1, 1] } ] } ] }