@abaplint/runtime
Version:
Transpiler - Runtime
134 lines • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.loop = loop;
const binary_search_1 = require("../binary_search");
const types_1 = require("../types");
function determineFromTo(array, topEquals, key) {
if (topEquals === undefined) {
// if there is no WHERE supplied, its using the sorting of the secondary key
return { from: 1, to: array.length };
}
let from = 0;
let to = array.length;
// todo: multi field
const keyField = key.keyFields[0].toLowerCase();
const keyValue = topEquals[keyField];
if (keyField && keyValue) {
from = (0, binary_search_1.binarySearchFrom)(array, from, to, keyField, keyValue);
to = (0, binary_search_1.binarySearchTo)(array, from, to, keyField, keyValue);
// console.dir("from: " + from + ", to: " + to);
}
return {
from: from,
to: to,
};
}
// todo: rewrite, this is a mess & hack & slow
function dynamicToWhere(condition, evaluate) {
// console.dir(condition);
let text = condition.replace(/ AND /gi, " && ").replace(/ OR /gi, " || ").replace(/ = /gi, " EQ ").replace(/ <> /gi, " NE ");
// console.dir(text);
if (evaluate === undefined) {
throw new Error("Dynamic WHERE evaluation function is not defined");
}
const matches = text.matchAll(/([\w-]+)\s+(\w+)\s+([<>\w-]+)/gi);
for (const match of matches) {
const left = match[1];
const comparator = match[2].toLowerCase();
let right = "";
// console.dir({left, right});
const cleft = "i." + left.toLowerCase().replace(/-/g, ".get().");
const rightMatches = match[3].matchAll(/<(\w+)>-(\w+)/gi);
for (const rightMatch of rightMatches) {
const name = "fs_" + rightMatch[1].toLowerCase() + "_";
right = `evaluate("${name}").get()["${rightMatch[2].toLowerCase()}"]`;
}
if (right === "") {
right = `evaluate("${match[3]}")`;
}
if (comparator === "in") {
const cnew = `abap.compare.in(${cleft}, ${right})`;
text = text.replace(match[0], cnew);
}
else {
const cnew = `abap.compare.${comparator}(${cleft}, ${right})`;
text = text.replace(match[0], cnew);
}
}
// console.dir(text);
// @ts-ignore
return async (i) => {
// console.dir(i);
// eslint-disable-next-line no-eval
return eval(text);
};
}
async function* loop(table, options) {
if (table === undefined) {
throw new Error("LOOP at undefined");
}
else if (table instanceof types_1.FieldSymbol) {
const pnt = table.getPointer();
if (pnt === undefined) {
throw new Error("GETWA_NOT_ASSIGNED");
}
yield* loop(pnt, options);
return;
}
if (options?.dynamicWhere) {
const dynamicWhere = options.dynamicWhere;
const newOptions = { ...options };
delete newOptions.dynamicWhere;
newOptions.where = dynamicToWhere(dynamicWhere.condition, dynamicWhere.evaluate);
yield* loop(table, newOptions);
return;
}
const length = table.getArrayLength();
if (length === 0) {
abap.builtin.sy.get().subrc.set(4);
return;
}
let loopFrom = options?.from && options?.from.get() > 0 ? options.from.get() - 1 : 0;
let loopTo = options?.to && options.to.get() < length ? options.to.get() : length;
let array = [];
if (options?.usingKey && options.usingKey !== undefined && options.usingKey !== "primary_key") {
array = table.getSecondaryIndex(options.usingKey);
const { from, to } = determineFromTo(array, options.topEquals, table.getKeyByName(options.usingKey));
loopFrom = Math.max(loopFrom, from) - 1;
loopTo = Math.min(loopTo, to);
}
else {
array = table.array();
}
const loopController = table.startLoop(loopFrom, loopTo, array);
let entered = false;
try {
const isStructured = array[0] instanceof types_1.Structure;
while (loopController.index < loopController.loopTo) {
if (loopController.index > array.length) {
break;
}
const current = array[loopController.index];
if (options?.where) {
const row = isStructured ? current.get() : { table_line: current };
if (await options.where(row) === false) {
loopController.index++;
continue;
}
}
abap.builtin.sy.get().tabix.set(loopController.index + 1);
entered = true;
yield current;
loopController.index++;
if (options?.to === undefined && options?.usingKey === undefined) {
// extra rows might have been inserted inside the loop
loopController.loopTo = array.length;
}
}
}
finally {
table.unregisterLoop(loopController);
abap.builtin.sy.get().subrc.set(entered ? 0 : 4);
}
}
//# sourceMappingURL=loop.js.map