@abaplint/runtime 2.13.87 → 2.13.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/builtin/_position.d.ts +12 -0
- package/build/src/builtin/_position.js +20 -0
- package/build/src/builtin/contains_any_not_of.d.ts +10 -0
- package/build/src/builtin/contains_any_not_of.js +28 -0
- package/build/src/builtin/contains_any_of.d.ts +10 -0
- package/build/src/builtin/contains_any_of.js +28 -0
- package/build/src/builtin/count.js +5 -4
- package/build/src/builtin/escape.js +2 -1
- package/build/src/builtin/find.js +3 -2
- package/build/src/builtin/find_any_not_of.js +4 -3
- package/build/src/builtin/find_any_of.js +4 -3
- package/build/src/builtin/index.d.ts +2 -0
- package/build/src/builtin/index.js +2 -0
- package/build/src/builtin/insert.js +4 -3
- package/build/src/builtin/repeat.js +2 -1
- package/build/src/builtin/replace.js +6 -7
- package/build/src/builtin/segment.js +2 -4
- package/build/src/builtin/shift_left.js +3 -5
- package/build/src/builtin/substring.js +3 -2
- package/build/src/compare/gt.js +5 -12
- package/build/src/operators/add.js +8 -0
- package/build/src/operators/minus.js +8 -0
- package/build/src/operators/mod.d.ts +2 -2
- package/build/src/operators/mod.js +5 -6
- package/build/src/operators/multiply.js +8 -0
- package/build/src/statements/create_data.js +23 -4
- package/build/src/statements/create_object.d.ts +17 -0
- package/build/src/statements/create_object.js +45 -0
- package/build/src/statements/index.d.ts +2 -0
- package/build/src/statements/index.js +2 -0
- package/build/src/statements/loop.js +20 -1
- package/build/src/types/integer.d.ts +1 -0
- package/build/src/types/integer.js +11 -3
- package/build/src/types/integer8.js +1 -1
- package/build/src/types/table.js +11 -2
- package/package.json +2 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ICharacter } from "../types/_character";
|
|
2
|
+
import { INumeric } from "../types/_numeric";
|
|
3
|
+
/** Reads an offset, length or occurrence argument as a number.
|
|
4
|
+
*
|
|
5
|
+
* parse() rather than get(): INumeric.get() promises a number, but Float and DecFloat34
|
|
6
|
+
* hand out their ABAP display form instead, ie. "1,2000000000000000E+01". Reading that
|
|
7
|
+
* back as a position keeps only the leading digit of the mantissa, so a length of 12
|
|
8
|
+
* silently becomes 1. nmin( ) and nmax( ) return a Float, and the syntax check lets them
|
|
9
|
+
* through where it rejects a declared TYPE f, so they are the way a float gets here.
|
|
10
|
+
*
|
|
11
|
+
* Rounded because ABAP converts the argument to type i, the same as assigning to one. */
|
|
12
|
+
export declare function position(input: INumeric | ICharacter | string | number | undefined): number | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.position = position;
|
|
4
|
+
const _parse_1 = require("../operators/_parse");
|
|
5
|
+
/** Reads an offset, length or occurrence argument as a number.
|
|
6
|
+
*
|
|
7
|
+
* parse() rather than get(): INumeric.get() promises a number, but Float and DecFloat34
|
|
8
|
+
* hand out their ABAP display form instead, ie. "1,2000000000000000E+01". Reading that
|
|
9
|
+
* back as a position keeps only the leading digit of the mantissa, so a length of 12
|
|
10
|
+
* silently becomes 1. nmin( ) and nmax( ) return a Float, and the syntax check lets them
|
|
11
|
+
* through where it rejects a declared TYPE f, so they are the way a float gets here.
|
|
12
|
+
*
|
|
13
|
+
* Rounded because ABAP converts the argument to type i, the same as assigning to one. */
|
|
14
|
+
function position(input) {
|
|
15
|
+
if (input === undefined) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return Math.round((0, _parse_1.parse)(input));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=_position.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { String } from "../types";
|
|
2
|
+
import { ICharacter } from "../types/_character";
|
|
3
|
+
import { INumeric } from "../types/_numeric";
|
|
4
|
+
export interface IContainsAnyNotOfInput {
|
|
5
|
+
val: ICharacter | string;
|
|
6
|
+
sub: ICharacter | string;
|
|
7
|
+
off?: INumeric | number;
|
|
8
|
+
len?: INumeric | number;
|
|
9
|
+
}
|
|
10
|
+
export declare function contains_any_not_of(input: IContainsAnyNotOfInput): String;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contains_any_not_of = contains_any_not_of;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const throw_error_1 = require("../throw_error");
|
|
6
|
+
function contains_any_not_of(input) {
|
|
7
|
+
const val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
|
+
const sub = typeof input.sub === "string" ? input.sub : input.sub.get();
|
|
9
|
+
const off = typeof input.off === "number" ? input.off : input.off?.get() || 0;
|
|
10
|
+
const len = typeof input.len === "number" ? input.len : input.len?.get();
|
|
11
|
+
if (off < 0 || off > val.length) {
|
|
12
|
+
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
13
|
+
}
|
|
14
|
+
if (len !== undefined && (len < 0 || off + len > val.length)) {
|
|
15
|
+
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
16
|
+
}
|
|
17
|
+
const end = len === undefined ? val.length : off + len;
|
|
18
|
+
const characters = new Set(sub.split(""));
|
|
19
|
+
let found = false;
|
|
20
|
+
for (let i = off; i < end; i++) {
|
|
21
|
+
if (!characters.has(val.charAt(i))) {
|
|
22
|
+
found = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return new types_1.String().set(found ? "X" : " ");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=contains_any_not_of.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { String } from "../types";
|
|
2
|
+
import { ICharacter } from "../types/_character";
|
|
3
|
+
import { INumeric } from "../types/_numeric";
|
|
4
|
+
export interface IContainsAnyOfInput {
|
|
5
|
+
val: ICharacter | string;
|
|
6
|
+
sub: ICharacter | string;
|
|
7
|
+
off?: INumeric | number;
|
|
8
|
+
len?: INumeric | number;
|
|
9
|
+
}
|
|
10
|
+
export declare function contains_any_of(input: IContainsAnyOfInput): String;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contains_any_of = contains_any_of;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const throw_error_1 = require("../throw_error");
|
|
6
|
+
function contains_any_of(input) {
|
|
7
|
+
const val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
|
+
const sub = typeof input.sub === "string" ? input.sub : input.sub.get();
|
|
9
|
+
const off = typeof input.off === "number" ? input.off : input.off?.get() || 0;
|
|
10
|
+
const len = typeof input.len === "number" ? input.len : input.len?.get();
|
|
11
|
+
if (off < 0 || off > val.length) {
|
|
12
|
+
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
13
|
+
}
|
|
14
|
+
if (len !== undefined && (len < 0 || off + len > val.length)) {
|
|
15
|
+
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
16
|
+
}
|
|
17
|
+
const end = len === undefined ? val.length : off + len;
|
|
18
|
+
const characters = new Set(sub.split(""));
|
|
19
|
+
let found = false;
|
|
20
|
+
for (let i = off; i < end; i++) {
|
|
21
|
+
if (characters.has(val.charAt(i))) {
|
|
22
|
+
found = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return new types_1.String().set(found ? "X" : " ");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=contains_any_of.js.map
|
|
@@ -4,15 +4,16 @@ exports.count = count;
|
|
|
4
4
|
const abap_regex_1 = require("../abap_regex");
|
|
5
5
|
const compare_1 = require("../compare");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
|
+
const _position_1 = require("./_position");
|
|
7
8
|
function count(input) {
|
|
8
9
|
let found = 0;
|
|
9
10
|
let val = input.val.get();
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const off = (0, _position_1.position)(input.off);
|
|
12
|
+
if (off !== undefined) {
|
|
12
13
|
val = val.substring(off);
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const len = (0, _position_1.position)(input.len);
|
|
16
|
+
if (len !== undefined) {
|
|
16
17
|
val = val.substring(0, len);
|
|
17
18
|
}
|
|
18
19
|
let reg = "";
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.escape = escape;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
|
+
const _position_1 = require("./_position");
|
|
5
6
|
function escape(input) {
|
|
6
7
|
let val = typeof input.val === "string" ? input.val : input.val.get();
|
|
7
|
-
const format =
|
|
8
|
+
const format = (0, _position_1.position)(input.format);
|
|
8
9
|
// todo, optimize/cache regexes
|
|
9
10
|
switch (format) {
|
|
10
11
|
case 1: // e_xml_attr
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.find = find;
|
|
4
4
|
const throw_error_1 = require("../throw_error");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function find(input) {
|
|
7
8
|
let val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
9
|
if (input.len !== undefined) {
|
|
@@ -32,8 +33,8 @@ function find(input) {
|
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
35
|
const sub = typeof input.sub === "string" ? input.sub : input.sub?.get();
|
|
35
|
-
let off =
|
|
36
|
-
let occ =
|
|
36
|
+
let off = (0, _position_1.position)(input.off) || 0;
|
|
37
|
+
let occ = (0, _position_1.position)(input.occ);
|
|
37
38
|
if (occ === 0) {
|
|
38
39
|
(0, throw_error_1.throwError)("CX_SY_STRG_PAR_VAL");
|
|
39
40
|
}
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.find_any_not_of = find_any_not_of;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const throw_error_1 = require("../throw_error");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function find_any_not_of(input) {
|
|
7
8
|
const val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
9
|
const sub = typeof input.sub === "string" ? input.sub : input.sub.get();
|
|
9
|
-
const off =
|
|
10
|
-
const len =
|
|
11
|
-
let occ =
|
|
10
|
+
const off = (0, _position_1.position)(input.off) || 0;
|
|
11
|
+
const len = (0, _position_1.position)(input.len);
|
|
12
|
+
let occ = (0, _position_1.position)(input.occ);
|
|
12
13
|
if (occ === 0) {
|
|
13
14
|
(0, throw_error_1.throwError)("CX_SY_STRG_PAR_VAL");
|
|
14
15
|
}
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.find_any_of = find_any_of;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const throw_error_1 = require("../throw_error");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function find_any_of(input) {
|
|
7
8
|
const val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
9
|
const sub = typeof input.sub === "string" ? input.sub : input.sub.get();
|
|
9
|
-
const off =
|
|
10
|
-
const len =
|
|
11
|
-
let occ =
|
|
10
|
+
const off = (0, _position_1.position)(input.off) || 0;
|
|
11
|
+
const len = (0, _position_1.position)(input.len);
|
|
12
|
+
let occ = (0, _position_1.position)(input.occ);
|
|
12
13
|
if (occ === 0) {
|
|
13
14
|
(0, throw_error_1.throwError)("CX_SY_STRG_PAR_VAL");
|
|
14
15
|
}
|
|
@@ -8,6 +8,8 @@ export * from "./ceil";
|
|
|
8
8
|
export * from "./concat_lines_of";
|
|
9
9
|
export * from "./condense";
|
|
10
10
|
export * from "./contains";
|
|
11
|
+
export * from "./contains_any_not_of";
|
|
12
|
+
export * from "./contains_any_of";
|
|
11
13
|
export * from "./cos";
|
|
12
14
|
export * from "./cosh";
|
|
13
15
|
export * from "./count_any_of";
|
|
@@ -25,6 +25,8 @@ __exportStar(require("./ceil"), exports);
|
|
|
25
25
|
__exportStar(require("./concat_lines_of"), exports);
|
|
26
26
|
__exportStar(require("./condense"), exports);
|
|
27
27
|
__exportStar(require("./contains"), exports);
|
|
28
|
+
__exportStar(require("./contains_any_not_of"), exports);
|
|
29
|
+
__exportStar(require("./contains_any_of"), exports);
|
|
28
30
|
__exportStar(require("./cos"), exports);
|
|
29
31
|
__exportStar(require("./cosh"), exports);
|
|
30
32
|
__exportStar(require("./count_any_of"), exports);
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.insert = insert;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
|
+
const _position_1 = require("./_position");
|
|
5
6
|
function insert(input) {
|
|
6
|
-
let offset = 0;
|
|
7
|
-
if (
|
|
8
|
-
offset =
|
|
7
|
+
let offset = (0, _position_1.position)(input.off);
|
|
8
|
+
if (offset === undefined) {
|
|
9
|
+
offset = 0;
|
|
9
10
|
}
|
|
10
11
|
const value = input.val.getOffset({ offset: 0, length: offset }).get() +
|
|
11
12
|
input.sub.get() +
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.repeat = repeat;
|
|
4
4
|
const string_1 = require("../types/string");
|
|
5
|
+
const _position_1 = require("./_position");
|
|
5
6
|
function repeat(input) {
|
|
6
7
|
const val = typeof input.val === "string" ? input.val : input.val.get();
|
|
7
|
-
return new string_1.String().set(val.repeat(input.occ
|
|
8
|
+
return new string_1.String().set(val.repeat((0, _position_1.position)(input.occ)));
|
|
8
9
|
}
|
|
9
10
|
//# sourceMappingURL=repeat.js.map
|
|
@@ -4,6 +4,7 @@ exports.replace = replace;
|
|
|
4
4
|
const string_1 = require("../types/string");
|
|
5
5
|
const abap_regex_1 = require("../abap_regex");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
|
+
const _position_1 = require("./_position");
|
|
7
8
|
function dereference(input) {
|
|
8
9
|
if (input instanceof types_1.FieldSymbol) {
|
|
9
10
|
const pointer = input.getPointer();
|
|
@@ -58,14 +59,12 @@ function replace(input) {
|
|
|
58
59
|
else if (regexInput) {
|
|
59
60
|
sub = new RegExp(abap_regex_1.ABAPRegExp.convert(regexInput.get()), "g");
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
const offset = (0, _position_1.position)(input.off);
|
|
63
|
+
const length = (0, _position_1.position)(input.len);
|
|
64
|
+
if (offset !== undefined && length !== undefined && typeof source === "string") {
|
|
64
65
|
val = val.substring(0, offset) + wi + val.substring(offset + length);
|
|
65
66
|
}
|
|
66
|
-
else if (
|
|
67
|
-
const offset = input.off.get();
|
|
68
|
-
const length = input.len.get();
|
|
67
|
+
else if (offset !== undefined && length !== undefined && !(typeof source === "string")) {
|
|
69
68
|
val = source.getOffset({ offset: 0, length: offset }).get() +
|
|
70
69
|
wi +
|
|
71
70
|
source.getOffset({ offset: offset + length }).get();
|
|
@@ -76,7 +75,7 @@ function replace(input) {
|
|
|
76
75
|
}
|
|
77
76
|
val = val.replace(sub, wi);
|
|
78
77
|
}
|
|
79
|
-
else if (input.occ && input.occ
|
|
78
|
+
else if (input.occ && (0, _position_1.position)(input.occ) === 0 && sub && wi !== undefined) {
|
|
80
79
|
if (typeof sub === "string") {
|
|
81
80
|
sub = new RegExp(sub, "g");
|
|
82
81
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.segment = segment;
|
|
4
4
|
const throw_error_1 = require("../throw_error");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function segment(input) {
|
|
7
8
|
let val = input.val;
|
|
8
9
|
if (typeof val !== "string") {
|
|
@@ -12,10 +13,7 @@ function segment(input) {
|
|
|
12
13
|
if (typeof sep !== "string") {
|
|
13
14
|
sep = sep.get();
|
|
14
15
|
}
|
|
15
|
-
let index = input.index;
|
|
16
|
-
if (typeof index !== "number") {
|
|
17
|
-
index = index.get();
|
|
18
|
-
}
|
|
16
|
+
let index = (0, _position_1.position)(input.index);
|
|
19
17
|
if (index === 0 || sep.length === 0) {
|
|
20
18
|
(0, throw_error_1.throwError)("CX_SY_STRG_PAR_VAL");
|
|
21
19
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.shift_left = shift_left;
|
|
4
4
|
const string_1 = require("../types/string");
|
|
5
5
|
const throw_error_1 = require("../throw_error");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function shift_left(input) {
|
|
7
8
|
let val = typeof input.val === "string" ? input.val : input.val.get();
|
|
8
9
|
if (input.sub) {
|
|
@@ -12,17 +13,14 @@ function shift_left(input) {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
else if (input.places) {
|
|
15
|
-
|
|
16
|
-
if (typeof places === "string") {
|
|
17
|
-
places = parseInt(places, 10);
|
|
18
|
-
}
|
|
16
|
+
const places = (0, _position_1.position)(input.places);
|
|
19
17
|
if (places > val.length) {
|
|
20
18
|
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
21
19
|
}
|
|
22
20
|
val = val.substring(places);
|
|
23
21
|
}
|
|
24
22
|
else if (input.circular) {
|
|
25
|
-
const leftShifts = input.circular
|
|
23
|
+
const leftShifts = (0, _position_1.position)(input.circular) % val.length;
|
|
26
24
|
val = val.slice(leftShifts) + val.slice(0, leftShifts);
|
|
27
25
|
}
|
|
28
26
|
else {
|
|
@@ -3,15 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.substring = substring;
|
|
4
4
|
const string_1 = require("../types/string");
|
|
5
5
|
const throw_error_1 = require("../throw_error");
|
|
6
|
+
const _position_1 = require("./_position");
|
|
6
7
|
function substring(input) {
|
|
7
|
-
let off = input?.off
|
|
8
|
+
let off = (0, _position_1.position)(input?.off);
|
|
8
9
|
if (off === undefined) {
|
|
9
10
|
off = 0;
|
|
10
11
|
}
|
|
11
12
|
else if (off < 0) {
|
|
12
13
|
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
13
14
|
}
|
|
14
|
-
const len = input?.len
|
|
15
|
+
const len = (0, _position_1.position)(input?.len);
|
|
15
16
|
if (len && len < 0) {
|
|
16
17
|
(0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS");
|
|
17
18
|
}
|
package/build/src/compare/gt.js
CHANGED
|
@@ -93,21 +93,14 @@ function gt(left, right) {
|
|
|
93
93
|
else {
|
|
94
94
|
r = right.get();
|
|
95
95
|
}
|
|
96
|
+
// a character operand is converted to the type of the numeric one it is
|
|
97
|
+
// compared with: '0.5' against a float is 0.5, not 0. parse() knows the
|
|
98
|
+
// rules, and an empty string is 0 there too
|
|
96
99
|
if (typeof l === "string" && typeof r === "number") {
|
|
97
|
-
|
|
98
|
-
l = 0;
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
l = parseInt(l, 10);
|
|
102
|
-
}
|
|
100
|
+
l = (0, _parse_1.parse)(l);
|
|
103
101
|
}
|
|
104
102
|
else if (typeof l === "number" && typeof r === "string") {
|
|
105
|
-
|
|
106
|
-
r = 0;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
r = parseInt(r, 10);
|
|
110
|
-
}
|
|
103
|
+
r = (0, _parse_1.parse)(r);
|
|
111
104
|
}
|
|
112
105
|
if (l === undefined) {
|
|
113
106
|
return true; // todo, not sure this is correct
|
|
@@ -11,6 +11,14 @@ function add(left, right) {
|
|
|
11
11
|
if (left instanceof types_1.Integer && right instanceof types_1.Integer) {
|
|
12
12
|
return new types_1.Integer().set(left.get() + right.get());
|
|
13
13
|
}
|
|
14
|
+
else if (left instanceof types_1.Float && right instanceof types_1.Float) {
|
|
15
|
+
// Two floats fall through the rest of the chain to exactly this, and
|
|
16
|
+
// float arithmetic is the most common thing there is: the remaining type
|
|
17
|
+
// tests all fail, and then parse() is called on each operand, which for a
|
|
18
|
+
// Float is getRaw(). It sits after the integer branch on purpose, so that
|
|
19
|
+
// integer arithmetic pays nothing for it.
|
|
20
|
+
return new types_1.Float().set(left.getRaw() + right.getRaw());
|
|
21
|
+
}
|
|
14
22
|
else if (typeof left === "number" && typeof right === "number"
|
|
15
23
|
&& Number.isInteger(left) && Number.isInteger(right)) {
|
|
16
24
|
return new types_1.Integer().set(left + right);
|
|
@@ -20,6 +20,14 @@ function minus(left, right) {
|
|
|
20
20
|
if (left instanceof types_1.Integer && right instanceof types_1.Integer) {
|
|
21
21
|
return new types_1.Integer().set(left.get() - right.get());
|
|
22
22
|
}
|
|
23
|
+
else if (left instanceof types_1.Float && right instanceof types_1.Float) {
|
|
24
|
+
// Two floats fall through the rest of the chain to exactly this, and
|
|
25
|
+
// float arithmetic is the most common thing there is: the remaining type
|
|
26
|
+
// tests all fail, and then parse() is called on each operand, which for a
|
|
27
|
+
// Float is getRaw(). It sits after the integer branch on purpose, so that
|
|
28
|
+
// integer arithmetic pays nothing for it.
|
|
29
|
+
return new types_1.Float().set(left.getRaw() - right.getRaw());
|
|
30
|
+
}
|
|
23
31
|
else if (left instanceof types_1.Integer8 || right instanceof types_1.Integer8) {
|
|
24
32
|
const l = left instanceof types_1.Integer8 ? left.get() : BigInt((0, _parse_1.parse)(left));
|
|
25
33
|
const r = right instanceof types_1.Integer8 ? right.get() : BigInt((0, _parse_1.parse)(right));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Integer, Integer8 } from "../types";
|
|
1
|
+
import { Float, Integer, Integer8 } from "../types";
|
|
2
2
|
import { ICharacter } from "../types/_character";
|
|
3
3
|
import { INumeric } from "../types/_numeric";
|
|
4
|
-
export declare function mod(left: INumeric | ICharacter | string | Integer8 | number, right: INumeric | Integer8 | ICharacter | string | number): Integer8 | Integer;
|
|
4
|
+
export declare function mod(left: INumeric | ICharacter | string | Integer8 | number, right: INumeric | Integer8 | ICharacter | string | number): Float | Integer8 | Integer;
|
|
@@ -36,12 +36,11 @@ function mod(left, right) {
|
|
|
36
36
|
if (val < 0) {
|
|
37
37
|
val = val * -1;
|
|
38
38
|
}
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
else {
|
|
44
|
-
return new types_1.Integer().set(val);
|
|
39
|
+
// the calculation type of the operands decides: with a float operand the
|
|
40
|
+
// remainder is a float, 2.75 MOD 1 is 0.75 and not 1
|
|
41
|
+
if (left instanceof types_1.Float || right instanceof types_1.Float) {
|
|
42
|
+
return new types_1.Float().set(val);
|
|
45
43
|
}
|
|
44
|
+
return new types_1.Integer().set(val);
|
|
46
45
|
}
|
|
47
46
|
//# sourceMappingURL=mod.js.map
|
|
@@ -14,6 +14,14 @@ function multiply(left, right) {
|
|
|
14
14
|
const val = left.get() * right.get();
|
|
15
15
|
return new types_1.Integer().set(val);
|
|
16
16
|
}
|
|
17
|
+
else if (left instanceof types_1.Float && right instanceof types_1.Float) {
|
|
18
|
+
// Two floats fall through the rest of the chain to exactly this, and
|
|
19
|
+
// float arithmetic is the most common thing there is: the remaining type
|
|
20
|
+
// tests all fail, and then parse() is called on each operand, which for a
|
|
21
|
+
// Float is getRaw(). It sits after the integer branch on purpose, so that
|
|
22
|
+
// integer arithmetic pays nothing for it.
|
|
23
|
+
return new types_1.Float().set(left.getRaw() * right.getRaw());
|
|
24
|
+
}
|
|
17
25
|
else if (typeof left === "number" && typeof right === "number"
|
|
18
26
|
&& Number.isInteger(left) && Number.isInteger(right)) {
|
|
19
27
|
const val = left * right;
|
|
@@ -4,6 +4,23 @@ exports.createData = createData;
|
|
|
4
4
|
const throw_error_1 = require("../throw_error");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const tableOptions = { withHeader: false, keyType: types_1.TableKeyType.default };
|
|
7
|
+
/** CREATE DATA ... TYPE REF TO <name>, both the static and the dynamic spelling.
|
|
8
|
+
* "REF TO data" is the generic case: the created data object is itself an
|
|
9
|
+
* unbound data reference, so the target points at a DataReference. Anything
|
|
10
|
+
* else names a class or interface. */
|
|
11
|
+
function createDataRefTo(target, name) {
|
|
12
|
+
if (name.toUpperCase() === "DATA") {
|
|
13
|
+
// a DataReference pointing at a DataReference, same shape GET REFERENCE OF
|
|
14
|
+
// a "REF TO data" variable produces - the declared types do not model the
|
|
15
|
+
// nesting, so this mirrors get_reference's cast
|
|
16
|
+
target.assign(new types_1.DataReference(undefined));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (abap.Classes[name.toUpperCase()] === undefined) {
|
|
20
|
+
(0, throw_error_1.throwError)("CX_SY_CREATE_DATA_ERROR");
|
|
21
|
+
}
|
|
22
|
+
target.assign(new abap.types.ABAPObject({ qualifiedName: name, RTTIName: name }));
|
|
23
|
+
}
|
|
7
24
|
function createData(target, options) {
|
|
8
25
|
// console.dir(options);
|
|
9
26
|
if (target instanceof types_1.FieldSymbol) {
|
|
@@ -70,10 +87,7 @@ function createData(target, options) {
|
|
|
70
87
|
target.assign(new types_1.Integer8());
|
|
71
88
|
}
|
|
72
89
|
else if (options.refTo === true) {
|
|
73
|
-
|
|
74
|
-
(0, throw_error_1.throwError)("CX_SY_CREATE_DATA_ERROR");
|
|
75
|
-
}
|
|
76
|
-
target.assign(new abap.types.ABAPObject({ qualifiedName: options.name, RTTIName: options.name }));
|
|
90
|
+
createDataRefTo(target, options.name);
|
|
77
91
|
}
|
|
78
92
|
else {
|
|
79
93
|
(0, throw_error_1.throwError)("CX_SY_CREATE_DATA_ERROR");
|
|
@@ -170,6 +184,11 @@ function createData(target, options) {
|
|
|
170
184
|
}
|
|
171
185
|
target.assign(abap.Classes[className][typeName.toLowerCase().trimEnd()].clone());
|
|
172
186
|
}
|
|
187
|
+
else if (options.refTo === true) {
|
|
188
|
+
// statically written "TYPE REF TO ...", the dynamic "TYPE REF TO (name)"
|
|
189
|
+
// variant is handled in the options.name branch above
|
|
190
|
+
createDataRefTo(target, options.typeName.trimEnd());
|
|
191
|
+
}
|
|
173
192
|
else {
|
|
174
193
|
throw new Error("CREATE DATA, unknown type " + options.typeName);
|
|
175
194
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CREATE OBJECT with a DYNAMIC class name, into a reference that has a static
|
|
3
|
+
* type: the class the name resolves to has to be compatible with that type.
|
|
4
|
+
*
|
|
5
|
+
* A system raises CX_SY_CREATE_OBJECT_ERROR when it is not, and it raises it
|
|
6
|
+
* BEFORE the constructor runs - so this is checked on the class, not on an
|
|
7
|
+
* instance. Without the check an unrelated class was simply assigned to the
|
|
8
|
+
* reference and the mismatch surfaced later as a raw javascript TypeError on
|
|
9
|
+
* the first member access, which no CATCH takes: a caller that guards its
|
|
10
|
+
* dynamic CREATE OBJECT the way the ABAP documentation asks for was not
|
|
11
|
+
* guarded at all.
|
|
12
|
+
*
|
|
13
|
+
* `targetType` is the class or interface object of the reference's static
|
|
14
|
+
* type and `targetName` its upper-case name; a generic `REF TO object` target
|
|
15
|
+
* passes both as undefined, and then there is nothing to check.
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkCreateObjectType(clas: any, targetType: any, targetName?: string): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkCreateObjectType = checkCreateObjectType;
|
|
4
|
+
const throw_error_1 = require("../throw_error");
|
|
5
|
+
/**
|
|
6
|
+
* CREATE OBJECT with a DYNAMIC class name, into a reference that has a static
|
|
7
|
+
* type: the class the name resolves to has to be compatible with that type.
|
|
8
|
+
*
|
|
9
|
+
* A system raises CX_SY_CREATE_OBJECT_ERROR when it is not, and it raises it
|
|
10
|
+
* BEFORE the constructor runs - so this is checked on the class, not on an
|
|
11
|
+
* instance. Without the check an unrelated class was simply assigned to the
|
|
12
|
+
* reference and the mismatch surfaced later as a raw javascript TypeError on
|
|
13
|
+
* the first member access, which no CATCH takes: a caller that guards its
|
|
14
|
+
* dynamic CREATE OBJECT the way the ABAP documentation asks for was not
|
|
15
|
+
* guarded at all.
|
|
16
|
+
*
|
|
17
|
+
* `targetType` is the class or interface object of the reference's static
|
|
18
|
+
* type and `targetName` its upper-case name; a generic `REF TO object` target
|
|
19
|
+
* passes both as undefined, and then there is nothing to check.
|
|
20
|
+
*/
|
|
21
|
+
function checkCreateObjectType(clas, targetType, targetName) {
|
|
22
|
+
if (clas === undefined || targetType === undefined) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (targetType.INTERNAL_TYPE === "CLAS") {
|
|
26
|
+
// the class itself or anything below it
|
|
27
|
+
if (clas === targetType || clas.prototype instanceof targetType) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (targetType.INTERNAL_TYPE === "INTF") {
|
|
32
|
+
// the same list the cast checks, and it carries the interfaces a
|
|
33
|
+
// superclass or a composed interface brings along
|
|
34
|
+
const list = clas.IMPLEMENTED_INTERFACES;
|
|
35
|
+
if (list?.some(i => i === targetName) === true) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// not something this can decide - leave it as it was
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
(0, throw_error_1.throwError)("CX_SY_CREATE_OBJECT_ERROR");
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=create_object.js.map
|
|
@@ -12,6 +12,7 @@ import { find } from "./find";
|
|
|
12
12
|
import { collect } from "./collect";
|
|
13
13
|
import { overlay } from "./overlay";
|
|
14
14
|
import { cast } from "./cast";
|
|
15
|
+
import { checkCreateObjectType } from "./create_object";
|
|
15
16
|
import { getBit } from "./get_bit";
|
|
16
17
|
import { readReport } from "./read_report";
|
|
17
18
|
import { getReference } from "./get_reference";
|
|
@@ -58,6 +59,7 @@ export declare class Statements {
|
|
|
58
59
|
assert: typeof assert;
|
|
59
60
|
assign: typeof assign;
|
|
60
61
|
cast: typeof cast;
|
|
62
|
+
checkCreateObjectType: typeof checkCreateObjectType;
|
|
61
63
|
collect: typeof collect;
|
|
62
64
|
concatenate: typeof concatenate;
|
|
63
65
|
condense: typeof condense;
|
|
@@ -15,6 +15,7 @@ const find_1 = require("./find");
|
|
|
15
15
|
const collect_1 = require("./collect");
|
|
16
16
|
const overlay_1 = require("./overlay");
|
|
17
17
|
const cast_1 = require("./cast");
|
|
18
|
+
const create_object_1 = require("./create_object");
|
|
18
19
|
const get_bit_1 = require("./get_bit");
|
|
19
20
|
const read_report_1 = require("./read_report");
|
|
20
21
|
const get_reference_1 = require("./get_reference");
|
|
@@ -61,6 +62,7 @@ class Statements {
|
|
|
61
62
|
assert = assert_1.assert;
|
|
62
63
|
assign = assign_1.assign;
|
|
63
64
|
cast = cast_1.cast;
|
|
65
|
+
checkCreateObjectType = create_object_1.checkCreateObjectType;
|
|
64
66
|
collect = collect_1.collect;
|
|
65
67
|
concatenate = concatenate_1.concatenate;
|
|
66
68
|
condense = condense_1.condense;
|
|
@@ -110,6 +110,24 @@ async function* loop(table, options) {
|
|
|
110
110
|
}
|
|
111
111
|
const loopController = table.startLoop(loopFrom, loopTo, array);
|
|
112
112
|
let entered = false;
|
|
113
|
+
// ABAP hands sy-tabix back the way it found it. A LOOP owns sy-tabix only
|
|
114
|
+
// for as long as it runs; leaving it, by ENDLOOP or EXIT or RETURN or an
|
|
115
|
+
// exception, puts back whatever the enclosing loop had. Without that an
|
|
116
|
+
// inner loop, or a method that happens to contain one, silently rewrites
|
|
117
|
+
// the row number the outer loop is standing on, and the outer body reads
|
|
118
|
+
// the inner loop's last index as its own.
|
|
119
|
+
const outerTabix = abap.builtin.sy.get().tabix.get();
|
|
120
|
+
// A hashed table has no row number to report, and ABAP says so by leaving
|
|
121
|
+
// sy-tabix at 0 for the whole loop rather than by inventing a position.
|
|
122
|
+
// The same goes for a loop that reads an index table through a hash
|
|
123
|
+
// secondary key. Handing out 1, 2, 3 there looks helpful and is a lie the
|
|
124
|
+
// caller cannot tell from the truth.
|
|
125
|
+
const usedKey = options?.usingKey === undefined || options.usingKey === "primary_key"
|
|
126
|
+
? undefined
|
|
127
|
+
: table.getKeyByName(options.usingKey);
|
|
128
|
+
const hasRowNumber = usedKey !== undefined
|
|
129
|
+
? usedKey.type !== types_1.TableAccessType.hashed
|
|
130
|
+
: !(table instanceof types_1.HashedTable);
|
|
113
131
|
try {
|
|
114
132
|
const isStructured = array[0] instanceof types_1.Structure;
|
|
115
133
|
while (loopController.index < loopController.loopTo) {
|
|
@@ -124,7 +142,7 @@ async function* loop(table, options) {
|
|
|
124
142
|
continue;
|
|
125
143
|
}
|
|
126
144
|
}
|
|
127
|
-
abap.builtin.sy.get().tabix.set(loopController.index + 1);
|
|
145
|
+
abap.builtin.sy.get().tabix.set(hasRowNumber ? loopController.index + 1 : 0);
|
|
128
146
|
entered = true;
|
|
129
147
|
options?.atLast?.(loopController.index + 1 >= loopController.loopTo);
|
|
130
148
|
yield current;
|
|
@@ -138,6 +156,7 @@ async function* loop(table, options) {
|
|
|
138
156
|
finally {
|
|
139
157
|
table.unregisterLoop(loopController);
|
|
140
158
|
abap.builtin.sy.get().subrc.set(entered ? 0 : 4);
|
|
159
|
+
abap.builtin.sy.get().tabix.set(outerTabix);
|
|
141
160
|
}
|
|
142
161
|
}
|
|
143
162
|
//# sourceMappingURL=loop.js.map
|
|
@@ -7,6 +7,7 @@ export declare const DIGITS: RegExp;
|
|
|
7
7
|
export declare const MAX_INTEGER = 2147483647;
|
|
8
8
|
export declare const MIN_INTEGER = -2147483648;
|
|
9
9
|
export declare function toInteger(value: string, exception?: boolean): number;
|
|
10
|
+
export declare function roundHalfAwayFromZero(value: number): number;
|
|
10
11
|
export declare class Integer implements INumeric {
|
|
11
12
|
private value;
|
|
12
13
|
private constant;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Integer = exports.MIN_INTEGER = exports.MAX_INTEGER = exports.DIGITS = void 0;
|
|
4
4
|
exports.toInteger = toInteger;
|
|
5
|
+
exports.roundHalfAwayFromZero = roundHalfAwayFromZero;
|
|
5
6
|
const throw_error_1 = require("../throw_error");
|
|
6
7
|
const float_1 = require("./float");
|
|
7
8
|
const hex_1 = require("./hex");
|
|
@@ -29,7 +30,14 @@ function toInteger(value, exception = true) {
|
|
|
29
30
|
throw new Error("CONVT_NO_NUMBER");
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
return
|
|
33
|
+
return roundHalfAwayFromZero(parseFloat(value));
|
|
34
|
+
}
|
|
35
|
+
// ABAP rounds a half away from zero when a float is moved to an integer,
|
|
36
|
+
// on both sides: 0.5 is 1 and -0.5 is -1. Math.round rounds a half towards
|
|
37
|
+
// positive infinity, so -0.5 was 0 (and -0 at that)
|
|
38
|
+
function roundHalfAwayFromZero(value) {
|
|
39
|
+
const rounded = value < 0 ? -Math.round(-value) : Math.round(value);
|
|
40
|
+
return rounded === 0 ? 0 : rounded;
|
|
33
41
|
}
|
|
34
42
|
class Integer {
|
|
35
43
|
value;
|
|
@@ -67,7 +75,7 @@ class Integer {
|
|
|
67
75
|
throw new Error("Changing constant");
|
|
68
76
|
}
|
|
69
77
|
if (typeof value === "number") {
|
|
70
|
-
this.value =
|
|
78
|
+
this.value = roundHalfAwayFromZero(value);
|
|
71
79
|
}
|
|
72
80
|
else if (value instanceof Integer) {
|
|
73
81
|
this.set(value.get());
|
|
@@ -82,7 +90,7 @@ class Integer {
|
|
|
82
90
|
this.set(Number(value.get()));
|
|
83
91
|
}
|
|
84
92
|
else if (value instanceof float_1.Float || value instanceof decfloat34_1.DecFloat34) {
|
|
85
|
-
this.set(
|
|
93
|
+
this.set(roundHalfAwayFromZero(value.getRaw()));
|
|
86
94
|
}
|
|
87
95
|
else if (value instanceof hex_1.Hex || value instanceof xstring_1.XString || value instanceof hex_uint8_1.HexUInt8) {
|
|
88
96
|
const hex = value.get();
|
|
@@ -47,7 +47,7 @@ class Integer8 {
|
|
|
47
47
|
this.value = BigInt(value);
|
|
48
48
|
}
|
|
49
49
|
else if (value instanceof float_1.Float || value instanceof decfloat34_1.DecFloat34) {
|
|
50
|
-
this.set(
|
|
50
|
+
this.set((0, integer_1.roundHalfAwayFromZero)(value.getRaw()));
|
|
51
51
|
}
|
|
52
52
|
else if (value instanceof hex_1.Hex || value instanceof xstring_1.XString || value instanceof hex_uint8_1.HexUInt8) {
|
|
53
53
|
if (value.get().length === 16) {
|
package/build/src/types/table.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Table = exports.HashedTable = exports.TableFactory = exports.LoopController = exports.TableKeyType = exports.TableAccessType = void 0;
|
|
4
4
|
const integer_1 = require("./integer");
|
|
5
|
+
const float_1 = require("./float");
|
|
5
6
|
const abap_object_1 = require("./abap_object");
|
|
6
7
|
const string_1 = require("./string");
|
|
7
8
|
const structure_1 = require("./structure");
|
|
@@ -294,8 +295,12 @@ class HashedTable {
|
|
|
294
295
|
cloneRow(item) {
|
|
295
296
|
// make sure to do conversion if needed
|
|
296
297
|
if (typeof item === "number") {
|
|
298
|
+
// a raw number is what the numeric built-ins return (sin, cos, sqrt,
|
|
299
|
+
// abs, floor, ...): a whole one is an integer, anything else is a
|
|
300
|
+
// float, and wrapping every one as an Integer first rounded a sine
|
|
301
|
+
// table to zeros before the row ever saw the value
|
|
297
302
|
const tmp = this.getRowType().clone();
|
|
298
|
-
tmp.set(new integer_1.Integer().set(item));
|
|
303
|
+
tmp.set(Number.isInteger(item) ? new integer_1.Integer().set(item) : new float_1.Float().set(item));
|
|
299
304
|
return tmp;
|
|
300
305
|
}
|
|
301
306
|
else if (typeof item === "string") {
|
|
@@ -564,8 +569,12 @@ class Table {
|
|
|
564
569
|
cloneRow(item) {
|
|
565
570
|
// make sure to do conversion if needed
|
|
566
571
|
if (typeof item === "number") {
|
|
572
|
+
// a raw number is what the numeric built-ins return (sin, cos, sqrt,
|
|
573
|
+
// abs, floor, ...): a whole one is an integer, anything else is a
|
|
574
|
+
// float, and wrapping every one as an Integer first rounded a sine
|
|
575
|
+
// table to zeros before the row ever saw the value
|
|
567
576
|
const tmp = this.getRowType().clone();
|
|
568
|
-
tmp.set(new integer_1.Integer().set(item));
|
|
577
|
+
tmp.set(Number.isInteger(item) ? new integer_1.Integer().set(item) : new float_1.Float().set(item));
|
|
569
578
|
return tmp;
|
|
570
579
|
}
|
|
571
580
|
else if (typeof item === "string") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abaplint/runtime",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.88",
|
|
4
4
|
"description": "Transpiler - Runtime",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"typings": "build/src/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@types/mocha": "^10.0.10",
|
|
34
34
|
"@types/node": "^26.4.1",
|
|
35
35
|
"chai": "^6.2.2",
|
|
36
|
-
"mocha": "^12.0.
|
|
36
|
+
"mocha": "^12.0.2",
|
|
37
37
|
"source-map-support": "^0.5.21",
|
|
38
38
|
"typescript": "^6.0.3"
|
|
39
39
|
},
|