const { ButtonMachine } = require('../../src/node_modules/buttons'); const run_code = (expecting, code, debug=false) => { let machine = new ButtonMachine(code); machine.run(debug); expect(machine.stack_top).toBe(expecting); return machine; } it('Can do addition', () => { run_code(3, [ ['PUSH', 1], ['PUSH', 2], ['ADD'], ]) }); it('Can do subtraction', () => { run_code(1, [ ['PUSH', 2], ['PUSH', 1], ['SUB'], ]) }) it('Can do multiplication', () => { run_code(20, [ ['PUSH', 10], ['PUSH', 2], ['MUL'], ]) }) it('Can do division', () => { run_code(5, [ ['PUSH', 10], ['PUSH', 2], ['DIV'], ]) }) it('Can do modulus', () => { run_code(0, [ ['PUSH', 10], ['PUSH', 2], ['MOD'], ]) }) it('Can loop until the end of clicks', () => { run_code(43, [ ['PUSH', 1], ['PUSH', 1], ['ADD'], ['JUMP', 1] ]); }); it('Can do zero test for jump', () => { run_code(0, [ ['PUSH', 20], // start at 20 ['PUSH', 1], // decrement by 1 ['SUB'], ['JZ', 5], // if we're at 0 jumps to the end ['JUMP', 1] // the previous test fails so it jumps to loop again ]); }); it('Can do NOT zero test for jump', () => { run_code(-19, [ ['PUSH', -20], // start at 20 ['PUSH', 1], // decrement by 1 ['ADD'], ['JNZ', 5], // if we're at 0 jumps to the end ['JUMP', 1] // the previous test fails so it jumps to loop again ]); }); it('Can store and restor', () => { run_code(150, [ ['PUSH', 100], // start with 100 ['STOR', 'AX'], // put it in the regA register ['PUSH', 50], // push 50 on too ['ADD'], // add those for 150 ['RSTOR', 'AX'],// recover the original 100 ['SUB'] // sub and should be 150 ]); }); it('Halts on bad registers', () => { run_code(0, [ ['PUSH', 0], ['STOR', 'AX'], ['RSTOR', 'BAD NAME'], // should cause a halt here ['PUSH', 100], ['ADD'] ]); }); it('Can halt on purpose', () => { let machine = run_code(0, [ ['PUSH', 0], ['HALT', 'Done on purpose.'] ]); expect(machine.halted).toBe(true); expect(machine.error).toBe('Done on purpose.'); });