FlowControl.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /**
  2. * Flow Control operations.
  3. *
  4. * @author n1474335 [n1474335@gmail.com]
  5. * @copyright Crown Copyright 2016
  6. * @license Apache-2.0
  7. *
  8. * @namespace
  9. */
  10. const FlowControl = {
  11. /**
  12. * @constant
  13. * @default
  14. */
  15. FORK_DELIM: "\\n",
  16. /**
  17. * @constant
  18. * @default
  19. */
  20. MERGE_DELIM: "\\n",
  21. /**
  22. * Fork operation.
  23. *
  24. * @param {Object} state - The current state of the recipe.
  25. * @param {number} state.progress - The current position in the recipe.
  26. * @param {Dish} state.dish - The Dish being operated on.
  27. * @param {Operation[]} state.op_list - The list of operations in the recipe.
  28. * @returns {Object} The updated state of the recipe.
  29. */
  30. run_fork: function(state) {
  31. var op_list = state.op_list,
  32. input_type = op_list[state.progress].input_type,
  33. output_type = op_list[state.progress].output_type,
  34. input = state.dish.get(input_type),
  35. ings = op_list[state.progress].get_ing_values(),
  36. split_delim = ings[0],
  37. merge_delim = ings[1],
  38. sub_op_list = [],
  39. inputs = [];
  40. if (input)
  41. inputs = input.split(split_delim);
  42. // Create sub_op_list for each tranche to operate on
  43. // (all remaining operations unless we encounter a Merge)
  44. for (var i = state.progress + 1; i < op_list.length; i++) {
  45. if (op_list[i].name === "Merge" && !op_list[i].is_disabled()) {
  46. break;
  47. } else {
  48. sub_op_list.push(op_list[i]);
  49. }
  50. }
  51. var recipe = new Recipe(),
  52. output = "",
  53. progress;
  54. recipe.add_operations(sub_op_list);
  55. // Run recipe over each tranche
  56. for (i = 0; i < inputs.length; i++) {
  57. var dish = new Dish(inputs[i], input_type);
  58. progress = recipe.execute(dish, 0);
  59. output += dish.get(output_type) + merge_delim;
  60. }
  61. state.dish.set(output, output_type);
  62. state.progress += progress;
  63. return state;
  64. },
  65. /**
  66. * Merge operation.
  67. *
  68. * @param {Object} state - The current state of the recipe.
  69. * @param {number} state.progress - The current position in the recipe.
  70. * @param {Dish} state.dish - The Dish being operated on.
  71. * @param {Operation[]} state.op_list - The list of operations in the recipe.
  72. * @returns {Object} The updated state of the recipe.
  73. */
  74. run_merge: function(state) {
  75. // No need to actually do anything here. The fork operation will
  76. // merge when it sees this operation.
  77. return state;
  78. },
  79. /**
  80. * @constant
  81. * @default
  82. */
  83. JUMP_NUM: 0,
  84. /**
  85. * @constant
  86. * @default
  87. */
  88. MAX_JUMPS: 10,
  89. /**
  90. * Jump operation.
  91. *
  92. * @param {Object} state - The current state of the recipe.
  93. * @param {number} state.progress - The current position in the recipe.
  94. * @param {Dish} state.dish - The Dish being operated on.
  95. * @param {Operation[]} state.op_list - The list of operations in the recipe.
  96. * @param {number} state.num_jumps - The number of jumps taken so far.
  97. * @returns {Object} The updated state of the recipe.
  98. */
  99. run_jump: function(state) {
  100. var ings = state.op_list[state.progress].get_ing_values(),
  101. jump_num = ings[0],
  102. max_jumps = ings[1];
  103. if (state.num_jumps >= max_jumps) {
  104. throw "Reached maximum jumps, sorry!";
  105. }
  106. state.progress += jump_num;
  107. state.num_jumps++;
  108. return state;
  109. },
  110. /**
  111. * Conditional Jump operation.
  112. *
  113. * @param {Object} state - The current state of the recipe.
  114. * @param {number} state.progress - The current position in the recipe.
  115. * @param {Dish} state.dish - The Dish being operated on.
  116. * @param {Operation[]} state.op_list - The list of operations in the recipe.
  117. * @param {number} state.num_jumps - The number of jumps taken so far.
  118. * @returns {Object} The updated state of the recipe.
  119. */
  120. run_cond_jump: function(state) {
  121. var ings = state.op_list[state.progress].get_ing_values(),
  122. dish = state.dish,
  123. regex_str = ings[0],
  124. jump_num = ings[1],
  125. max_jumps = ings[2];
  126. if (state.num_jumps >= max_jumps) {
  127. throw "Reached maximum jumps, sorry!";
  128. }
  129. if (regex_str !== "" && dish.get(Dish.STRING).search(regex_str) > -1) {
  130. state.progress += jump_num;
  131. state.num_jumps++;
  132. }
  133. return state;
  134. },
  135. /**
  136. * Return operation.
  137. *
  138. * @param {Object} state - The current state of the recipe.
  139. * @param {number} state.progress - The current position in the recipe.
  140. * @param {Dish} state.dish - The Dish being operated on.
  141. * @param {Operation[]} state.op_list - The list of operations in the recipe.
  142. * @returns {Object} The updated state of the recipe.
  143. */
  144. run_return: function(state) {
  145. state.progress = state.op_list.length;
  146. return state;
  147. },
  148. };