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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
"homepage": "https://github.com/abaplint/transpiler_poc#readme",
"devDependencies": {
"@abaplint/core": "^2.120.5",
"@abaplint/core": "^2.120.6",
"@eslint/compat": "^2.1.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "^9.39.4",
Expand Down
36 changes: 18 additions & 18 deletions packages/cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@abaplint/transpiler-cli",
"version": "2.13.46",
"version": "2.13.47",
"description": "Transpiler - Command Line Interface",
"funding": "https://github.com/sponsors/larshp",
"bin": {
Expand All @@ -27,8 +27,8 @@
"author": "abaplint",
"license": "MIT",
"devDependencies": {
"@abaplint/core": "^2.120.5",
"@abaplint/transpiler": "^2.13.46",
"@abaplint/core": "^2.120.6",
"@abaplint/transpiler": "^2.13.47",
"@types/glob": "^8.1.0",
"@types/node": "^24.12.2",
"@types/progress": "^2.0.7",
Expand Down
22 changes: 11 additions & 11 deletions packages/extras/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions packages/extras/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
"author": "Heliconia Labs ApS",
"license": "PolyForm-Noncommercial-1.0.0",
"peerDependencies": {
"@abaplint/core": "^2.120.5",
"@abaplint/transpiler": "^2.13.46"
"@abaplint/core": "^2.120.6",
"@abaplint/transpiler": "^2.13.47"
},
"devDependencies": {
"@abaplint/core": "^2.120.5",
"@abaplint/transpiler": "^2.13.46",
"@abaplint/core": "^2.120.6",
"@abaplint/transpiler": "^2.13.47",
"@types/chai": "^4.3.20",
"@types/mocha": "^10.0.10",
"@types/node": "^24.13.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@abaplint/runtime",
"version": "2.13.46",
"version": "2.13.47",
"description": "Transpiler - Runtime",
"main": "build/src/index.js",
"typings": "build/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/builtin/abs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function abs(input: {val: number | string | ICharacter | INumeric}) {
} else if (typeof input.val === "string") {
num_in = parseFloat(input.val);
} else if (input.val instanceof Float) {
num_in = input.val.getRaw();
num_in = input.val.getCalculationValue();
} else {
num_in = parseFloat(input.val.get().toString());
}
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/builtin/ceil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function ceil(input: {val: number | string | ICharacter | INumeric}) {
} else if ( typeof input.val === "string") {
num_in = parseFloat(input.val);
} else if (input.val instanceof Float) {
num_in = input.val.getRaw();
num_in = input.val.getCalculationValue();
} else {
num_in = parseFloat(input.val.get().toString());
}
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/builtin/floor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function floor(input: {val: number | string | ICharacter | INumeric}) {
} else if (typeof input.val === "string") {
num_in = parseFloat(input.val);
} else if (input.val instanceof Float) {
num_in = input.val.getRaw();
num_in = input.val.getCalculationValue();
} else {
num_in = parseFloat(input.val.get().toString());
}
Expand Down
5 changes: 3 additions & 2 deletions packages/runtime/src/builtin/frac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ export function frac(input: {val: number | string | ICharacter | INumeric}) {
num_in = input.val;
} else if (typeof input.val === "string") {
num_in = parseFloat(input.val);
} else if (input.val instanceof DecFloat34
|| input.val instanceof Float) {
} else if (input.val instanceof Float) {
num_in = input.val.getCalculationValue();
} else if (input.val instanceof DecFloat34) {
num_in = input.val.getRaw();
} else {
num_in = parseFloat(input.val.get().toString());
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/builtin/trunc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function trunc(input: {val: number | string | ICharacter | INumeric}) {
} else if (typeof input.val === "string") {
num_in = parseFloat(input.val);
} else if (input.val instanceof Float) {
num_in = input.val.getRaw();
num_in = input.val.getCalculationValue();
} else {
num_in = parseFloat(input.val.get().toString());
}
Expand Down
6 changes: 3 additions & 3 deletions packages/runtime/src/operators/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export function add(left: INumeric | ICharacter | string | number | Float | Inte
return new Integer().set(left.get() + right);

} else if ((left instanceof String || left instanceof Character) && isIntegerCharacter(left) && right instanceof Integer) {
return new Integer().set(Number.parseInt(left.get(), 10) + right.get());
return new Integer().set(Number.parseInt(left.get(), 10) + right.get()).clearIntegerCalculationType();
} else if ((right instanceof String || right instanceof Character) && isIntegerCharacter(right) && left instanceof Integer) {
return new Integer().set(left.get() + Number.parseInt(right.get(), 10));
return new Integer().set(left.get() + Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
} else if ((left instanceof String || left instanceof Character)
&& (right instanceof String || right instanceof Character)
&& isIntegerCharacter(left)
&& isIntegerCharacter(right)) {
return new Integer().set(Number.parseInt(left.get(), 10) + Number.parseInt(right.get(), 10));
return new Integer().set(Number.parseInt(left.get(), 10) + Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
} else if (left instanceof Integer8) {
if (right instanceof Integer8) {
return new Integer8().set(left.get() + right.get());
Expand Down
15 changes: 13 additions & 2 deletions packages/runtime/src/operators/divide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,16 @@ export function divide(left: INumeric | ICharacter | Integer8 | string | number,
}
const val = l / r;

return new Float().set(val);
}
const ret = new Float().set(val);
if (isIntegerOperand(left) && isIntegerOperand(right)) {
ret.setIntegerCalculationType();
}
return ret;
}

function isIntegerOperand(val: INumeric | ICharacter | Integer8 | string | number): boolean {
if (val instanceof Integer) {
return val.isIntegerCalculationType();
}
return val instanceof Integer8;
}
4 changes: 2 additions & 2 deletions packages/runtime/src/operators/minus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export function minus(left: INumeric | ICharacter | string | Integer8 | number |
return new Integer().set(left.get() - right);

} else if ((left instanceof String || left instanceof Character) && Number.isInteger(Number(left.get())) && right instanceof Integer) {
return new Integer().set(Number.parseInt(left.get(), 10) - right.get());
return new Integer().set(Number.parseInt(left.get(), 10) - right.get()).clearIntegerCalculationType();
} else if ((right instanceof String || right instanceof Character) && Number.isInteger(Number(right)) && left instanceof Integer) {
return new Integer().set(left.get() - Number.parseInt(right.get(), 10));
return new Integer().set(left.get() - Number.parseInt(right.get(), 10)).clearIntegerCalculationType();
}

return new Float().set(parse(left) - parse(right));
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/src/operators/multiply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export function multiply(left: INumeric | ICharacter | string | Integer8 | numbe
return new Integer().set(val);
} else if ((left instanceof String || left instanceof Character) && Number.isInteger(Number(left.get())) && right instanceof Integer) {
const val = Number.parseInt(left.get(), 10) * right.get();
return new Integer().set(val);
return new Integer().set(val).clearIntegerCalculationType();
} else if ((right instanceof String || right instanceof Character) && Number.isInteger(Number(right)) && left instanceof Integer) {
const val = left.get() * Number.parseInt(right.get(), 10);
return new Integer().set(val);
return new Integer().set(val).clearIntegerCalculationType();
}

return new Float().set(parse(left) * parse(right));
Expand Down
18 changes: 18 additions & 0 deletions packages/runtime/src/types/float.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function getNumberParts(x: number) {

export class Float {
private value: number;
private integerCalculationType = false;
private readonly qualifiedName: string | undefined;

public constructor(input?: {qualifiedName?: string}) {
Expand All @@ -35,6 +36,23 @@ export class Float {
return n;
}

/** ABAP calculates in type i if all operands are integers, ie. "3 / 2" is 2. The exact value is
* kept here, so assigning to a float or packed target, which raises the calculation type, still
* gives the exact result. Consumers without a target type must use getCalculationValue() */
public setIntegerCalculationType(): Float {
this.integerCalculationType = true;
return this;
}

/** value as seen by the calculation type, ie. rounded if the calculation type is integer */
public getCalculationValue(): number {
if (this.integerCalculationType === true) {
// ABAP rounds half away from zero
return this.value < 0 ? -Math.round(-this.value) : Math.round(this.value);
}
return this.value;
}

public getQualifiedName() {
return this.qualifiedName;
}
Expand Down
12 changes: 12 additions & 0 deletions packages/runtime/src/types/integer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,25 @@ export function toInteger(value: string, exception = true): number {
export class Integer implements INumeric {
private value: number;
private constant: boolean = false;
private integerCalculationType = true;
private readonly qualifiedName: string | undefined;

public constructor(input?: {qualifiedName?: string}) {
this.value = 0;
this.qualifiedName = input?.qualifiedName;
}

/** ABAP determines the calculation type from the operand types, character-like operands raise it
* above type i even if the intermediate result is integer, ie. "'1.0' * 18 / 16" is not rounded */
public clearIntegerCalculationType(): Integer {
this.integerCalculationType = false;
return this;
}

public isIntegerCalculationType(): boolean {
return this.integerCalculationType;
}

public getQualifiedName() {
return this.qualifiedName;
}
Expand Down
Loading
Loading