Fixed integer calculations

This commit is contained in:
4eb0da
2023-12-12 12:33:53 +03:00
parent ca4bfd68e4
commit 70b5fc8199
5 changed files with 98 additions and 2 deletions
+1
View File
@@ -12331,6 +12331,7 @@
"client/web/divkit/tests/bundles/client.test.ts":"divkit/public/client/web/divkit/tests/bundles/client.test.ts",
"client/web/divkit/tests/bundles/package.json":"divkit/public/client/web/divkit/tests/bundles/package.json",
"client/web/divkit/tests/bundles/server.test.ts":"divkit/public/client/web/divkit/tests/bundles/server.test.ts",
"client/web/divkit/tests/expressions/expressions-integers.test.ts":"divkit/public/client/web/divkit/tests/expressions/expressions-integers.test.ts",
"client/web/divkit/tests/expressions/expressions-with-out-bigint.test.ts":"divkit/public/client/web/divkit/tests/expressions/expressions-with-out-bigint.test.ts",
"client/web/divkit/tests/expressions/expressions.test.ts":"divkit/public/client/web/divkit/tests/expressions/expressions.test.ts",
"client/web/divkit/tests/expressions/nobigint/functions_arithmetic_integer.json":"divkit/public/client/web/divkit/tests/expressions/nobigint/functions_arithmetic_integer.json",
@@ -33,6 +33,7 @@ function arrayGetter(jsType: string, runtimeType: string) {
throw new Error('Cannot convert value to integer.');
}
checkIntegerOverflow(ctx, val);
val = toBigInt(val);
}
if (jsType === 'string' && runtimeType === 'color') {
val = transformColorValue(val as string);
@@ -1,3 +1,4 @@
import { toBigInt } from '../bigint';
import { BOOLEAN, COLOR, DICT, INTEGER, NUMBER, STRING, URL } from '../const';
import { BooleanValue, DictValue, EvalContext, EvalTypes, EvalValue, IntegerValue, NumberValue, StringValue } from '../eval';
import { checkIntegerOverflow, transformColorValue } from '../utils';
@@ -42,6 +43,7 @@ function dictGetter(jsType: string, runtimeType: string) {
throw new Error('Cannot convert value to integer.');
}
checkIntegerOverflow(ctx, val);
val = toBigInt(val);
}
if (jsType === 'string' && runtimeType === 'color') {
val = transformColorValue(val as string);
@@ -2,7 +2,7 @@ import type { EvalContext, EvalValue, IntegerValue, NumberValue } from '../eval'
import { registerFunc } from './funcs';
import { INTEGER, MAX_NUMBER, MIN_NUMBER, NUMBER } from '../const';
import { checkIntegerOverflow, roundInteger } from '../utils';
import { absBigInt, bigIntZero, signBigInt, MAX_INT, MIN_INT } from '../bigint';
import { absBigInt, bigIntZero, signBigInt, MAX_INT, MIN_INT, toBigInt } from '../bigint';
function divInteger(ctx: EvalContext, arg0: IntegerValue, arg1: IntegerValue): EvalValue {
if (arg1.value === bigIntZero) {
@@ -297,7 +297,7 @@ function copySignInteger(ctx: EvalContext, arg0: IntegerValue, arg1: IntegerValu
if (arg1.value === bigIntZero) {
res = arg0.value;
} else if (arg0.value === bigIntZero) {
res = 0;
res = toBigInt(0);
} else {
const sign = signBigInt(arg1.value);
@@ -0,0 +1,92 @@
import { evalExpression, EvalResult } from '../../src/expressions/eval';
import { valToString } from '../../src/expressions/utils';
import { parse } from '../../src/expressions/expressions';
import { createVariable } from '../../src/expressions/variable';
const path = require('path');
const fs = require('fs');
const dir = path.resolve(__filename, '../../../../../../test_data/expression_test_data');
const tests = fs.readdirSync(dir);
function convertVals(val: EvalResult) {
if (val.type === 'boolean') {
return {
type: 'boolean',
value: val.value ? 1 : 0
};
} else if (val.type === 'integer') {
return {
type: 'integer',
// values in json is out of range already
value: Number(val.value)
};
} else if (val.type === 'datetime' && val.value instanceof Date) {
return {
type: 'datetime',
value: valToString(val)
};
}
return val;
}
function runCase(item: any) {
const vars = new Map();
if (item.variables) {
for (const variable of item.variables) {
vars.set(variable.name, createVariable(variable.name, variable.type, variable.value));
}
}
let ast;
try {
ast = parse(item.expression, {
startRule: 'JsonStringContents'
});
} catch (err: any) {
if (item.expected.value) {
expect({
type: 'error',
value: err.message
}).toEqual(item.expected);
} else {
expect('error').toEqual(item.expected.type);
}
return;
}
const res = evalExpression(vars, ast);
expect(typeof res.result.value).toEqual('bigint');
}
describe('expressions-integers', () => {
for (const file of tests) {
const name = file.replace('.json', '');
const contents = require(path.resolve(dir, file));
if (contents.cases) {
const counter: Record<string, number> = {};
describe(name, () => {
for (const item of contents.cases) {
if (item.platforms.includes('web') && item.expected?.type === 'integer') {
let name = item.name;
if (!counter[name]) {
counter[name] = 0;
}
name += ` : ${counter[name]++}`;
it(name, () => {
runCase(item);
});
} else {
// eslint-disable-next-line no-console
console.log('skip', file, name, item.name);
}
}
});
}
}
});