@abaplint/runtime 2.13.45 → 2.13.47

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.
@@ -11,7 +11,7 @@ function abs(input) {
11
11
  num_in = parseFloat(input.val);
12
12
  }
13
13
  else if (input.val instanceof types_1.Float) {
14
- num_in = input.val.getRaw();
14
+ num_in = input.val.getCalculationValue();
15
15
  }
16
16
  else {
17
17
  num_in = parseFloat(input.val.get().toString());
@@ -11,7 +11,7 @@ function ceil(input) {
11
11
  num_in = parseFloat(input.val);
12
12
  }
13
13
  else if (input.val instanceof types_1.Float) {
14
- num_in = input.val.getRaw();
14
+ num_in = input.val.getCalculationValue();
15
15
  }
16
16
  else {
17
17
  num_in = parseFloat(input.val.get().toString());
@@ -11,7 +11,7 @@ function floor(input) {
11
11
  num_in = parseFloat(input.val);
12
12
  }
13
13
  else if (input.val instanceof types_1.Float) {
14
- num_in = input.val.getRaw();
14
+ num_in = input.val.getCalculationValue();
15
15
  }
16
16
  else {
17
17
  num_in = parseFloat(input.val.get().toString());
@@ -12,8 +12,10 @@ function frac(input) {
12
12
  else if (typeof input.val === "string") {
13
13
  num_in = parseFloat(input.val);
14
14
  }
15
- else if (input.val instanceof types_1.DecFloat34
16
- || input.val instanceof types_1.Float) {
15
+ else if (input.val instanceof types_1.Float) {
16
+ num_in = input.val.getCalculationValue();
17
+ }
18
+ else if (input.val instanceof types_1.DecFloat34) {
17
19
  num_in = input.val.getRaw();
18
20
  }
19
21
  else {
@@ -11,7 +11,7 @@ function trunc(input) {
11
11
  num_in = parseFloat(input.val);
12
12
  }
13
13
  else if (input.val instanceof types_1.Float) {
14
- num_in = input.val.getRaw();
14
+ num_in = input.val.getCalculationValue();
15
15
  }
16
16
  else {
17
17
  num_in = parseFloat(input.val.get().toString());
@@ -22,16 +22,16 @@ function add(left, right) {
22
22
  return new types_1.Integer().set(left.get() + right);
23
23
  }
24
24
  else if ((left instanceof string_1.String || left instanceof types_1.Character) && isIntegerCharacter(left) && right instanceof types_1.Integer) {
25
- return new types_1.Integer().set(Number.parseInt(left.get(), 10) + right.get());
25
+ return new types_1.Integer().set(Number.parseInt(left.get(), 10) + right.get()).clearIntegerCalculationType();
26
26
  }
27
27
  else if ((right instanceof string_1.String || right instanceof types_1.Character) && isIntegerCharacter(right) && left instanceof types_1.Integer) {
28
- return new types_1.Integer().set(left.get() + Number.parseInt(right.get(), 10));
28
+ return new types_1.Integer().set(left.get() + Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
29
29
  }
30
30
  else if ((left instanceof string_1.String || left instanceof types_1.Character)
31
31
  && (right instanceof string_1.String || right instanceof types_1.Character)
32
32
  && isIntegerCharacter(left)
33
33
  && isIntegerCharacter(right)) {
34
- return new types_1.Integer().set(Number.parseInt(left.get(), 10) + Number.parseInt(right.get(), 10));
34
+ return new types_1.Integer().set(Number.parseInt(left.get(), 10) + Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
35
35
  }
36
36
  else if (left instanceof types_1.Integer8) {
37
37
  if (right instanceof types_1.Integer8) {
@@ -30,6 +30,16 @@ function divide(left, right) {
30
30
  }
31
31
  }
32
32
  const val = l / r;
33
- return new types_1.Float().set(val);
33
+ const ret = new types_1.Float().set(val);
34
+ if (isIntegerOperand(left) && isIntegerOperand(right)) {
35
+ ret.setIntegerCalculationType();
36
+ }
37
+ return ret;
38
+ }
39
+ function isIntegerOperand(val) {
40
+ if (val instanceof types_1.Integer) {
41
+ return val.isIntegerCalculationType();
42
+ }
43
+ return val instanceof types_1.Integer8;
34
44
  }
35
45
  //# sourceMappingURL=divide.js.map
@@ -36,10 +36,10 @@ function minus(left, right) {
36
36
  return new types_1.Integer().set(left.get() - right);
37
37
  }
38
38
  else if ((left instanceof string_1.String || left instanceof types_1.Character) && Number.isInteger(Number(left.get())) && right instanceof types_1.Integer) {
39
- return new types_1.Integer().set(Number.parseInt(left.get(), 10) - right.get());
39
+ return new types_1.Integer().set(Number.parseInt(left.get(), 10) - right.get()).clearIntegerCalculationType();
40
40
  }
41
41
  else if ((right instanceof string_1.String || right instanceof types_1.Character) && Number.isInteger(Number(right)) && left instanceof types_1.Integer) {
42
- return new types_1.Integer().set(left.get() - Number.parseInt(right.get(), 10));
42
+ return new types_1.Integer().set(left.get() - Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
43
43
  }
44
44
  return new types_1.Float().set((0, _parse_1.parse)(left) - (0, _parse_1.parse)(right));
45
45
  }
@@ -29,11 +29,11 @@ function multiply(left, right) {
29
29
  }
30
30
  else if ((left instanceof string_1.String || left instanceof types_1.Character) && Number.isInteger(Number(left.get())) && right instanceof types_1.Integer) {
31
31
  const val = Number.parseInt(left.get(), 10) * right.get();
32
- return new types_1.Integer().set(val);
32
+ return new types_1.Integer().set(val).clearIntegerCalculationType();
33
33
  }
34
34
  else if ((right instanceof string_1.String || right instanceof types_1.Character) && Number.isInteger(Number(right)) && left instanceof types_1.Integer) {
35
35
  const val = left.get() * Number.parseInt(right.get(), 10);
36
- return new types_1.Integer().set(val);
36
+ return new types_1.Integer().set(val).clearIntegerCalculationType();
37
37
  }
38
38
  return new types_1.Float().set((0, _parse_1.parse)(left) * (0, _parse_1.parse)(right));
39
39
  }
@@ -13,5 +13,5 @@ type options = {
13
13
  alphaInContext?: any;
14
14
  align?: "left" | "right";
15
15
  };
16
- export declare function templateFormatting(source: ICharacter | INumeric, options?: options): string;
16
+ export declare function templateFormatting(source: ICharacter | INumeric | number | string, options?: options): string;
17
17
  export {};
@@ -50,14 +50,24 @@ function templateFormatting(source, options) {
50
50
  text = source.toFixed(source.getDecimals());
51
51
  }
52
52
  }
53
+ else if (typeof source === "number" || typeof source === "string") {
54
+ text = source + "";
55
+ }
53
56
  else {
54
57
  text = source.get() + "";
55
58
  }
56
59
  if (options?.alpha === "out") {
57
- text = (0, alpha_1.alphaOut)(source);
60
+ if (typeof source === "number" || typeof source === "string") {
61
+ text = text.replace(/^0+/, "");
62
+ }
63
+ else {
64
+ text = (0, alpha_1.alphaOut)(source);
65
+ }
58
66
  }
59
67
  else if (options?.alpha === "in") {
60
- text = (0, alpha_1.alphaIn)(source, options.alphaInContext);
68
+ if (typeof source !== "number" && typeof source !== "string") {
69
+ text = (0, alpha_1.alphaIn)(source, options.alphaInContext);
70
+ }
61
71
  }
62
72
  if (options) {
63
73
  if (options.currency !== undefined) {
@@ -3,11 +3,18 @@ import { ICharacter } from "./_character";
3
3
  import { INumeric } from "./_numeric";
4
4
  export declare class Float {
5
5
  private value;
6
+ private integerCalculationType;
6
7
  private readonly qualifiedName;
7
8
  constructor(input?: {
8
9
  qualifiedName?: string;
9
10
  });
10
11
  clone(): Float;
12
+ /** ABAP calculates in type i if all operands are integers, ie. "3 / 2" is 2. The exact value is
13
+ * kept here, so assigning to a float or packed target, which raises the calculation type, still
14
+ * gives the exact result. Consumers without a target type must use getCalculationValue() */
15
+ setIntegerCalculationType(): Float;
16
+ /** value as seen by the calculation type, ie. rounded if the calculation type is integer */
17
+ getCalculationValue(): number;
11
18
  getQualifiedName(): string | undefined;
12
19
  set(value: INumeric | ICharacter | Hex | string | number): this;
13
20
  clear(): void;
@@ -21,6 +21,7 @@ function getNumberParts(x: number) {
21
21
  */
22
22
  class Float {
23
23
  value;
24
+ integerCalculationType = false;
24
25
  qualifiedName;
25
26
  constructor(input) {
26
27
  this.value = 0;
@@ -31,6 +32,21 @@ class Float {
31
32
  n.value = this.value;
32
33
  return n;
33
34
  }
35
+ /** ABAP calculates in type i if all operands are integers, ie. "3 / 2" is 2. The exact value is
36
+ * kept here, so assigning to a float or packed target, which raises the calculation type, still
37
+ * gives the exact result. Consumers without a target type must use getCalculationValue() */
38
+ setIntegerCalculationType() {
39
+ this.integerCalculationType = true;
40
+ return this;
41
+ }
42
+ /** value as seen by the calculation type, ie. rounded if the calculation type is integer */
43
+ getCalculationValue() {
44
+ if (this.integerCalculationType === true) {
45
+ // ABAP rounds half away from zero
46
+ return this.value < 0 ? -Math.round(-this.value) : Math.round(this.value);
47
+ }
48
+ return this.value;
49
+ }
34
50
  getQualifiedName() {
35
51
  return this.qualifiedName;
36
52
  }
@@ -9,10 +9,15 @@ export declare function toInteger(value: string, exception?: boolean): number;
9
9
  export declare class Integer implements INumeric {
10
10
  private value;
11
11
  private constant;
12
+ private integerCalculationType;
12
13
  private readonly qualifiedName;
13
14
  constructor(input?: {
14
15
  qualifiedName?: string;
15
16
  });
17
+ /** ABAP determines the calculation type from the operand types, character-like operands raise it
18
+ * above type i even if the intermediate result is integer, ie. "'1.0' * 18 / 16" is not rounded */
19
+ clearIntegerCalculationType(): Integer;
20
+ isIntegerCalculationType(): boolean;
16
21
  getQualifiedName(): string | undefined;
17
22
  clone(): Integer;
18
23
  setConstant(): this;
@@ -33,11 +33,21 @@ function toInteger(value, exception = true) {
33
33
  class Integer {
34
34
  value;
35
35
  constant = false;
36
+ integerCalculationType = true;
36
37
  qualifiedName;
37
38
  constructor(input) {
38
39
  this.value = 0;
39
40
  this.qualifiedName = input?.qualifiedName;
40
41
  }
42
+ /** ABAP determines the calculation type from the operand types, character-like operands raise it
43
+ * above type i even if the intermediate result is integer, ie. "'1.0' * 18 / 16" is not rounded */
44
+ clearIntegerCalculationType() {
45
+ this.integerCalculationType = false;
46
+ return this;
47
+ }
48
+ isIntegerCalculationType() {
49
+ return this.integerCalculationType;
50
+ }
41
51
  getQualifiedName() {
42
52
  return this.qualifiedName;
43
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/runtime",
3
- "version": "2.13.45",
3
+ "version": "2.13.47",
4
4
  "description": "Transpiler - Runtime",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",