diff --git a/src/core/lib/FlowControl.mjs b/src/core/lib/FlowControl.mjs new file mode 100644 index 00000000..b44c7037 --- /dev/null +++ b/src/core/lib/FlowControl.mjs @@ -0,0 +1,13 @@ +/** + * Returns the index of a label. + * + * @private + * @param {Object} state + * @param {string} name + * @returns {number} + */ +export function getLabelIndex(name, state) { + return state.opList.findIndex((operation) => { + return (operation.name === "Label") && (name === operation.ingValues[0]); + }); +} diff --git a/src/core/operations/Jump.mjs b/src/core/operations/Jump.mjs new file mode 100644 index 00000000..078b6db6 --- /dev/null +++ b/src/core/operations/Jump.mjs @@ -0,0 +1,66 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import { getLabelIndex } from "../lib/FlowControl"; + +/** + * Jump operation + */ +class Jump extends Operation { + + /** + * Jump constructor + */ + constructor() { + super(); + + this.name = "Jump"; + this.flowControl = true; + this.module = "Default"; + this.description = "Jump forwards or backwards to the specified Label"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Label name", + "type": "string", + "value": "" + }, + { + "name": "Maximum jumps (if jumping backwards)", + "type": "number", + "value": 10 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(state) { + const ings = state.opList[state.progress].ingValues; + const label = ings[0]; + const maxJumps = ings[1]; + const jmpIndex = getLabelIndex(label, state); + + if (state.numJumps >= maxJumps || jmpIndex === -1) { + log.debug("Maximum jumps reached or label cannot be found"); + return state; + } + + state.progress = jmpIndex; + state.numJumps++; + log.debug(`Jumping to label '${label}' at position ${jmpIndex} (jumps = ${state.numJumps})`); + return state; + + } + +} + +export default Jump; diff --git a/test/tests/operations/FlowControl.mjs b/test/tests/operations/FlowControl.mjs index 3b503646..df20974d 100644 --- a/test/tests/operations/FlowControl.mjs +++ b/test/tests/operations/FlowControl.mjs @@ -114,38 +114,38 @@ TestRegister.addTests([ // }, // ], // }, -// { -// name: "Jump: skips 1", -// input: [ -// "shouldnt be changed", -// ].join("\n"), -// expectedOutput: [ -// "shouldnt be changed", -// ].join("\n"), -// recipeConfig: [ -// { -// op: "Jump", -// args: ["skipReplace", 10], -// }, -// { -// op: "Find / Replace", -// args: [ -// { -// "option": "Regex", -// "string": "shouldnt be changed" -// }, -// "shouldnt be changed was changed", -// true, -// true, -// true, -// ], -// }, -// { -// op: "Label", -// args: ["skipReplace"] -// }, -// ], -// }, + { + name: "Jump: skips 1", + input: [ + "shouldnt be changed", + ].join("\n"), + expectedOutput: [ + "shouldnt be changed", + ].join("\n"), + recipeConfig: [ + { + op: "Jump", + args: ["skipReplace", 10], + }, + { + op: "Find / Replace", + args: [ + { + "option": "Regex", + "string": "shouldnt be changed" + }, + "shouldnt be changed was changed", + true, + true, + true, + ], + }, + { + op: "Label", + args: ["skipReplace"] + }, + ], + }, // { // name: "Conditional Jump: Skips 0", // input: [