Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions packages/runtime/src/statements/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ function dynamicToWhere(condition: string, evaluate: (name: string) => FieldSymb
throw new Error("Dynamic WHERE evaluation function is not defined");
}

const matches = text.matchAll(/([\w-]+)\s+(\w+)\s+([<>\w-]+)/gi);
const matches = text.matchAll(/([\w-]+)\s+(NOT\s+IN|\w+)\s+([<>\w-]+)/gi);
for (const match of matches) {
const left = match[1];
const comparator = match[2].toLowerCase();
const comparator = match[2].toLowerCase().replace(/\s+/g, " ");
let right = "";
// console.dir({left, right});

Expand All @@ -66,13 +66,21 @@ function dynamicToWhere(condition: string, evaluate: (name: string) => FieldSymb
right = `evaluate("${name}").get()["${rightMatch[2].toLowerCase()}"]`;
}

const fieldSymbol = match[3].match(/^<(\w+)>$/);
if (right === "" && fieldSymbol) {
right = `evaluate("fs_${fieldSymbol[1].toLowerCase()}_").getPointer()`;
}

if (right === "") {
right = `evaluate("${match[3]}")`;
right = `evaluate("${match[3].toLowerCase()}")`;
}

if (comparator === "in") {
const cnew = `abap.compare.in(${cleft}, ${right})`;
text = text.replace(match[0], cnew);
} else if (comparator === "not 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);
Expand Down
71 changes: 71 additions & 0 deletions test/statements/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,77 @@ ENDLOOP.`;
expect(abap.console.getTrimmed()).to.equal("2");
});

it("LOOP dynamic WHERE IN, upper case", async () => {
const code = `
TYPES: BEGIN OF ty,
field TYPE i,
END OF ty.
DATA range TYPE RANGE OF i.
DATA dynamic TYPE string.
DATA tab TYPE STANDARD TABLE OF ty.
DATA row LIKE LINE OF tab.

INSERT VALUE #( field = 2 ) INTO TABLE tab.
INSERT VALUE #( field = 3 ) INTO TABLE tab.
INSERT VALUE #( low = 2 option = 'EQ' sign = 'I' ) INTO TABLE range.
dynamic = 'FIELD IN RANGE'.
LOOP AT tab INTO row WHERE (dynamic).
WRITE / row-field.
ENDLOOP.`;
const js = await run(code);
const f = new AsyncFunction("abap", js);
await f(abap);
expect(abap.console.getTrimmed()).to.equal("2");
});

it("LOOP dynamic WHERE NOT IN", async () => {
const code = `
TYPES: BEGIN OF ty,
field TYPE i,
END OF ty.
DATA range TYPE RANGE OF i.
DATA dynamic TYPE string.
DATA tab TYPE STANDARD TABLE OF ty.
DATA row LIKE LINE OF tab.

INSERT VALUE #( field = 2 ) INTO TABLE tab.
INSERT VALUE #( field = 3 ) INTO TABLE tab.
INSERT VALUE #( low = 2 option = 'EQ' sign = 'I' ) INTO TABLE range.
dynamic = 'FIELD NOT IN RANGE'.
LOOP AT tab INTO row WHERE (dynamic).
WRITE / row-field.
ENDLOOP.`;
const js = await run(code);
const f = new AsyncFunction("abap", js);
await f(abap);
expect(abap.console.getTrimmed()).to.equal("3");
});

it("LOOP dynamic WHERE IN, field symbol range", async () => {
const code = `
TYPES: BEGIN OF ty,
field TYPE i,
END OF ty.
DATA range TYPE RANGE OF i.
DATA dynamic TYPE string.
DATA tab TYPE STANDARD TABLE OF ty.
DATA row LIKE LINE OF tab.
FIELD-SYMBOLS <range> LIKE range.

INSERT VALUE #( field = 2 ) INTO TABLE tab.
INSERT VALUE #( field = 3 ) INTO TABLE tab.
INSERT VALUE #( low = 2 option = 'EQ' sign = 'I' ) INTO TABLE range.
ASSIGN range TO <range>.
dynamic = 'FIELD IN <RANGE>'.
LOOP AT tab INTO row WHERE (dynamic).
WRITE / row-field.
ENDLOOP.`;
const js = await run(code);
const f = new AsyncFunction("abap", js);
await f(abap);
expect(abap.console.getTrimmed()).to.equal("2");
});

it("LOOP GROUP BY", async () => {
const code = `
TYPES:
Expand Down
Loading