diff --git a/packages/runtime/src/statements/concatenate.ts b/packages/runtime/src/statements/concatenate.ts index a0658804c..7cd75d8be 100644 --- a/packages/runtime/src/statements/concatenate.ts +++ b/packages/runtime/src/statements/concatenate.ts @@ -28,18 +28,22 @@ export function concatenate(input: IConcatenateInput) { } if (input.lines === true) { - const list: string[] = []; + let result = ""; const tab = input.source[0]; if (tab instanceof Table) { - for (const l of tab.array()) { - if (input.respectingBlanks !== true) { - list.push(l.get().trimEnd()); - } else { - list.push(l.get()); + const array = tab.array(); + const length = array.length; + const respectingBlanks = input.respectingBlanks === true; + const hasSeparator = sep.length > 0; + for (let i = 0; i < length; i++) { + if (hasSeparator === true && i > 0) { + result += sep; } + const value = array[i].get(); + result += respectingBlanks === true ? value : value.trimEnd(); } } - input.target.set(list.join(sep)); + input.target.set(result); } else { let result = ""; diff --git a/performance/index.ts b/performance/index.ts index 81bdef472..7563d7726 100644 --- a/performance/index.ts +++ b/performance/index.ts @@ -45,6 +45,7 @@ import {test39} from "./test39"; import {test40} from "./test40"; import {test41} from "./test41"; import {test42} from "./test42"; +import {test43} from "./test43"; // NOTE: does not run via Mocha @@ -102,6 +103,7 @@ const tests: Tests = [ {name: "40: eq string", abap: test40}, {name: "41: eq char, different lengths", abap: test41}, {name: "42: eq int with numc", abap: test42}, + {name: "43: CONCATENATE LINES OF", abap: test43}, ]; async function execute(t: Test) { diff --git a/performance/test43.ts b/performance/test43.ts new file mode 100644 index 000000000..62bec5f1d --- /dev/null +++ b/performance/test43.ts @@ -0,0 +1,12 @@ +export const test43 = ` +DATA lt_tab TYPE STANDARD TABLE OF string WITH DEFAULT KEY. +DATA lv_str TYPE string. + +DO 2000 TIMES. + APPEND 'foobar' TO lt_tab. +ENDDO. + +DO 1000 TIMES. + CONCATENATE LINES OF lt_tab INTO lv_str SEPARATED BY ','. +ENDDO. +`; diff --git a/test/statements/concatenate.ts b/test/statements/concatenate.ts index 80eb3ce7f..b08a22032 100644 --- a/test/statements/concatenate.ts +++ b/test/statements/concatenate.ts @@ -161,6 +161,46 @@ WRITE count.`; expect(abap.console.get()).to.equal("5"); }); + it("CONCATENATE LINES OF, empty table", async () => { + const code = ` +DATA lt_tab TYPE STANDARD TABLE OF string WITH DEFAULT KEY. +DATA res TYPE string. +res = 'foo'. +CONCATENATE LINES OF lt_tab INTO res SEPARATED BY '-'. +ASSERT res IS INITIAL.`; + const js = await run(code); + const f = new AsyncFunction("abap", js); + await f(abap); + }); + + it("CONCATENATE LINES OF, single line", async () => { + const code = ` +DATA lt_tab TYPE STANDARD TABLE OF string WITH DEFAULT KEY. +DATA res TYPE string. +APPEND 'foo' TO lt_tab. +CONCATENATE LINES OF lt_tab INTO res SEPARATED BY '--'. +ASSERT res = 'foo'.`; + const js = await run(code); + const f = new AsyncFunction("abap", js); + await f(abap); + }); + + it("CONCATENATE LINES OF, char table, trailing blanks removed", async () => { + const code = ` +TYPES char5 TYPE c LENGTH 5. +DATA lt_tab TYPE STANDARD TABLE OF char5 WITH DEFAULT KEY. +DATA res TYPE string. +APPEND 'ab' TO lt_tab. +APPEND 'cd' TO lt_tab. +CONCATENATE LINES OF lt_tab INTO res SEPARATED BY '--'. +ASSERT res = 'ab--cd'. +CONCATENATE LINES OF lt_tab INTO res. +ASSERT res = 'abcd'.`; + const js = await run(code); + const f = new AsyncFunction("abap", js); + await f(abap); + }); + it("Separated by INTF constant", async () => { const code = ` INTERFACE lif.