@ball-lang/engine 1.3.6 → 1.3.8
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/dist/compiled_engine.d.ts.map +1 -1
- package/dist/compiled_engine.js +81 -42
- package/dist/compiled_engine.js.map +1 -1
- package/dist/engine_setup.d.ts.map +1 -1
- package/dist/engine_setup.js +61 -2
- package/dist/engine_setup.js.map +1 -1
- package/package.json +1 -1
- package/src/compiled_engine.ts +73 -42
- package/src/engine_setup.ts +59 -2
package/src/compiled_engine.ts
CHANGED
|
@@ -677,17 +677,9 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
677
677
|
Object.defineProperty(sp, 'isNotEmpty', {
|
|
678
678
|
configurable: true, get() { return this.length !== 0; },
|
|
679
679
|
});
|
|
680
|
-
//
|
|
681
|
-
//
|
|
682
|
-
//
|
|
683
|
-
const _origObjDefProp = Object.defineProperty;
|
|
684
|
-
for (const boolProp of ['isEmpty', 'isNotEmpty']) {
|
|
685
|
-
if (!(undefined as any)?.[boolProp]) {
|
|
686
|
-
// Can't add properties to undefined/null, but we handle it in the
|
|
687
|
-
// generated code via ?.isEmpty fallback patterns. The preamble's
|
|
688
|
-
// protoWrap handles most cases.
|
|
689
|
-
}
|
|
690
|
-
}
|
|
680
|
+
// Note: undefined/null safety for .isEmpty/.isNotEmpty is handled in the
|
|
681
|
+
// generated code via optional-chaining (?.isEmpty) patterns and protoWrap;
|
|
682
|
+
// properties cannot be installed on undefined/null directly.
|
|
691
683
|
// Dart String methods not on JS String.
|
|
692
684
|
if (!sp.contains) sp.contains = function (s: any) { return this.includes(s); };
|
|
693
685
|
if (!sp.replaceFirst) sp.replaceFirst = function (from: any, to: any) {
|
|
@@ -893,7 +885,6 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
893
885
|
return Object.keys(this).filter((k: string) => !k.startsWith('__')).length;
|
|
894
886
|
});
|
|
895
887
|
|
|
896
|
-
// Number polyfills moved earlier (see "Dart Number polyfills" block above).
|
|
897
888
|
// runtimeType — Dart's Object.runtimeType. Returns the Dart-style
|
|
898
889
|
// type name for any JS value. Used by the compiled engine for type
|
|
899
890
|
// checking and error messages.
|
|
@@ -1569,7 +1560,7 @@ export class BallEngine {
|
|
|
1569
1560
|
let enumName = enumDesc.name;
|
|
1570
1561
|
let enumMap = {};
|
|
1571
1562
|
let enumValueList = enumDesc.value;
|
|
1572
|
-
for (
|
|
1563
|
+
for (let vi = 0; (vi < enumValueList.length); (vi++)) {
|
|
1573
1564
|
let v = __ball_index(enumValueList, vi);
|
|
1574
1565
|
let entry = { ['__type__']: enumName, ['name']: v.name, ['index']: v.number };
|
|
1575
1566
|
enumMap[v.name] = entry;
|
|
@@ -1887,19 +1878,23 @@ export class BallEngine {
|
|
|
1887
1878
|
}
|
|
1888
1879
|
} else {
|
|
1889
1880
|
if (!__ball_eq(inputMap, null)) {
|
|
1890
|
-
for (
|
|
1881
|
+
for (let i = 0; (i < params.length); (i++)) {
|
|
1891
1882
|
let p = __ball_index(params, i);
|
|
1892
1883
|
if ((p in inputMap)) {
|
|
1893
1884
|
scope.bind(p, __ball_index(inputMap, p));
|
|
1894
1885
|
} else {
|
|
1895
1886
|
if ((('arg' + __ball_to_string(i)) in inputMap)) {
|
|
1896
1887
|
scope.bind(p, __ball_index(inputMap, ('arg' + __ball_to_string(i))));
|
|
1888
|
+
} else {
|
|
1889
|
+
if ((((__ball_eq(i, 0) && __ball_eq(params.length, 1)) && ('value' in inputMap)) && this._isSetter(func))) {
|
|
1890
|
+
scope.bind(p, __ball_index(inputMap, 'value'));
|
|
1891
|
+
}
|
|
1897
1892
|
}
|
|
1898
1893
|
}
|
|
1899
1894
|
}
|
|
1900
1895
|
} else {
|
|
1901
1896
|
if (Array.isArray(input)) {
|
|
1902
|
-
for (
|
|
1897
|
+
for (let i = 0; ((i < params.length) && (i < input.length)); (i++)) {
|
|
1903
1898
|
scope.bind(__ball_index(params, i), __ball_index(input, i));
|
|
1904
1899
|
}
|
|
1905
1900
|
}
|
|
@@ -2033,7 +2028,7 @@ export class BallEngine {
|
|
|
2033
2028
|
let params = (hasMetadata(func) ? this._extractParams(func.metadata) : []);
|
|
2034
2029
|
let paramsMeta = (hasMetadata(func) ? this._extractParamsMeta(func.metadata) : []);
|
|
2035
2030
|
let resolvedParams = {};
|
|
2036
|
-
for (
|
|
2031
|
+
for (let i = 0; (i < params.length); (i++)) {
|
|
2037
2032
|
let param = __ball_index(params, i);
|
|
2038
2033
|
let value = __no_init__;
|
|
2039
2034
|
if ((param in inputMap)) {
|
|
@@ -2161,7 +2156,7 @@ export class BallEngine {
|
|
|
2161
2156
|
let resolvedParams = {};
|
|
2162
2157
|
let inputMap = this._asMap(input);
|
|
2163
2158
|
if (!__ball_eq(inputMap, null)) {
|
|
2164
|
-
for (
|
|
2159
|
+
for (let i = 0; (i < params.length); (i++)) {
|
|
2165
2160
|
let p = __ball_index(params, i);
|
|
2166
2161
|
let isThis = ((i < paramsMeta.length) && __ball_eq(__ball_index(__ball_index(paramsMeta, i), 'is_this'), true));
|
|
2167
2162
|
let val = __no_init__;
|
|
@@ -2239,7 +2234,7 @@ export class BallEngine {
|
|
|
2239
2234
|
})() ?? '');
|
|
2240
2235
|
let argNames = this._parseSuperArgs(argsStr);
|
|
2241
2236
|
let superInput = {};
|
|
2242
|
-
for (
|
|
2237
|
+
for (let i = 0; (i < argNames.length); (i++)) {
|
|
2243
2238
|
let token = __ball_index(argNames, i);
|
|
2244
2239
|
if ((token in resolvedParams)) {
|
|
2245
2240
|
superInput[('arg' + __ball_to_string(i))] = __ball_index(resolvedParams, token);
|
|
@@ -2273,7 +2268,7 @@ export class BallEngine {
|
|
|
2273
2268
|
let superCtorEntry = this._lookupConstructor(superclass);
|
|
2274
2269
|
if (!__ball_eq(superCtorEntry, null)) {
|
|
2275
2270
|
let superInput = {};
|
|
2276
|
-
for (
|
|
2271
|
+
for (let i = 0; (i < resolvedParams.length); (i++)) {
|
|
2277
2272
|
superInput[('arg' + __ball_to_string(i))] = resolvedParams.values.elementAt(i);
|
|
2278
2273
|
}
|
|
2279
2274
|
return this._callFunction(superCtorEntry.module, superCtorEntry.func, superInput);
|
|
@@ -3978,7 +3973,7 @@ export class BallEngine {
|
|
|
3978
3973
|
if ((!__ball_eq(ctorEntry, null) && hasMetadata(ctorEntry.func))) {
|
|
3979
3974
|
let params = this._extractParams(ctorEntry.func.metadata);
|
|
3980
3975
|
let paramsMeta = this._extractParamsMeta(ctorEntry.func.metadata);
|
|
3981
|
-
for (
|
|
3976
|
+
for (let i = 0; (i < params.length); (i++)) {
|
|
3982
3977
|
let param = __ball_index(params, i);
|
|
3983
3978
|
let value = __no_init__;
|
|
3984
3979
|
if ((param in fields)) {
|
|
@@ -4458,7 +4453,7 @@ export class BallEngine {
|
|
|
4458
4453
|
}
|
|
4459
4454
|
}
|
|
4460
4455
|
if (!(paramNames.length === 0)) {
|
|
4461
|
-
for (
|
|
4456
|
+
for (let i = 0; (i < paramNames.length); (i++)) {
|
|
4462
4457
|
let p = __ball_index(paramNames, i);
|
|
4463
4458
|
if (!lambdaScope.has(p)) {
|
|
4464
4459
|
if ((p in inputMap)) {
|
|
@@ -5772,13 +5767,24 @@ export class BallEngine {
|
|
|
5772
5767
|
return null;
|
|
5773
5768
|
}
|
|
5774
5769
|
let result = __no_init__;
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5770
|
+
let repeat = true;
|
|
5771
|
+
while (repeat) {
|
|
5772
|
+
repeat = false;
|
|
5773
|
+
try {
|
|
5774
|
+
result = await this._evalExpression(body, scope);
|
|
5775
|
+
} catch (__ball_active_error) {
|
|
5776
|
+
const e = __ball_active_error;
|
|
5777
|
+
let signal = e;
|
|
5778
|
+
if ((((signal instanceof _FlowSignal) && __ball_eq(signal.kind, 'goto')) && __ball_eq(signal.label, label))) {
|
|
5779
|
+
repeat = true;
|
|
5780
|
+
} else {
|
|
5781
|
+
throw __ball_active_error;
|
|
5782
|
+
}
|
|
5779
5783
|
}
|
|
5780
|
-
|
|
5781
|
-
|
|
5784
|
+
if ((((!repeat && (result instanceof _FlowSignal)) && __ball_eq(result.kind, 'goto')) && __ball_eq(result.label, label))) {
|
|
5785
|
+
repeat = true;
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5782
5788
|
return result;
|
|
5783
5789
|
}
|
|
5784
5790
|
|
|
@@ -5859,7 +5865,19 @@ export class BallEngine {
|
|
|
5859
5865
|
if (false /* BallMap is Map in TS */) {
|
|
5860
5866
|
unwrappedSelf = self.entries;
|
|
5861
5867
|
} else {
|
|
5862
|
-
|
|
5868
|
+
if ((typeof self === 'number' || self instanceof BallDouble)) {
|
|
5869
|
+
unwrappedSelf = self;
|
|
5870
|
+
} else {
|
|
5871
|
+
if ((typeof self === 'number' && Number.isInteger(self))) {
|
|
5872
|
+
unwrappedSelf = self.value;
|
|
5873
|
+
} else {
|
|
5874
|
+
if ((typeof self === 'number' || self instanceof BallDouble)) {
|
|
5875
|
+
unwrappedSelf = self.value;
|
|
5876
|
+
} else {
|
|
5877
|
+
unwrappedSelf = self;
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5863
5881
|
}
|
|
5864
5882
|
}
|
|
5865
5883
|
}
|
|
@@ -5912,7 +5930,7 @@ export class BallEngine {
|
|
|
5912
5930
|
else if ((__sw === 'sort')) {
|
|
5913
5931
|
if ((typeof arg0 === 'function')) {
|
|
5914
5932
|
let sorted = [...self];
|
|
5915
|
-
for (
|
|
5933
|
+
for (let j = 1; (j < sorted.length); (j++)) {
|
|
5916
5934
|
let key = __ball_index(sorted, j);
|
|
5917
5935
|
let k = __ball_sub(j, 1);
|
|
5918
5936
|
while ((k >= 0)) {
|
|
@@ -6637,7 +6655,10 @@ export class BallEngine {
|
|
|
6637
6655
|
const input = i;
|
|
6638
6656
|
return this._stdConvert(i, ((v) => {
|
|
6639
6657
|
const input = v;
|
|
6640
|
-
|
|
6658
|
+
if ((typeof v === 'number' || v instanceof BallDouble)) {
|
|
6659
|
+
return __ball_to_string(v);
|
|
6660
|
+
}
|
|
6661
|
+
return __ball_to_string(new BallDouble(v));
|
|
6641
6662
|
}));
|
|
6642
6663
|
}), ['string_to_int']: ((i) => {
|
|
6643
6664
|
const input = i;
|
|
@@ -6649,7 +6670,7 @@ export class BallEngine {
|
|
|
6649
6670
|
const input = i;
|
|
6650
6671
|
return this._stdConvert(i, ((v) => {
|
|
6651
6672
|
const input = v;
|
|
6652
|
-
return __ball_parse_double(v);
|
|
6673
|
+
return new BallDouble(__ball_parse_double(v));
|
|
6653
6674
|
}));
|
|
6654
6675
|
}), ['to_double']: ((i) => {
|
|
6655
6676
|
const input = i;
|
|
@@ -6940,7 +6961,7 @@ export class BallEngine {
|
|
|
6940
6961
|
}));
|
|
6941
6962
|
return sorted;
|
|
6942
6963
|
}
|
|
6943
|
-
for (
|
|
6964
|
+
for (let j = 1; (j < sorted.length); (j++)) {
|
|
6944
6965
|
let key = __ball_index(sorted, j);
|
|
6945
6966
|
let k = __ball_sub(j, 1);
|
|
6946
6967
|
while ((k >= 0)) {
|
|
@@ -7029,10 +7050,16 @@ export class BallEngine {
|
|
|
7029
7050
|
if ((r != null)) {
|
|
7030
7051
|
r = await r;
|
|
7031
7052
|
}
|
|
7032
|
-
if (
|
|
7033
|
-
|
|
7053
|
+
if (false /* BallList is List in TS */) {
|
|
7054
|
+
for (const item of r.items) {
|
|
7055
|
+
result = (result.push(item), result);
|
|
7056
|
+
}
|
|
7034
7057
|
} else {
|
|
7035
|
-
|
|
7058
|
+
if (Array.isArray(r)) {
|
|
7059
|
+
__ball_push_all(result, r);
|
|
7060
|
+
} else {
|
|
7061
|
+
result = (result.push(r), result);
|
|
7062
|
+
}
|
|
7036
7063
|
}
|
|
7037
7064
|
}
|
|
7038
7065
|
return result;
|
|
@@ -7378,7 +7405,8 @@ export class BallEngine {
|
|
|
7378
7405
|
return new _FlowSignal('yield_each', { value: this._extractUnaryArg(i) });
|
|
7379
7406
|
}), ['symbol']: ((i) => {
|
|
7380
7407
|
const input = i;
|
|
7381
|
-
|
|
7408
|
+
let name = this._extractField(i, 'value');
|
|
7409
|
+
return (('Symbol("' + __ball_to_string(name)) + '")');
|
|
7382
7410
|
}), ['type_literal']: ((i) => {
|
|
7383
7411
|
const input = i;
|
|
7384
7412
|
return this._extractField(i, 'type');
|
|
@@ -8096,7 +8124,7 @@ export class BallEngine {
|
|
|
8096
8124
|
}
|
|
8097
8125
|
this._trackMemoryAllocation(__ball_mul(length, _ballPointerBytes));
|
|
8098
8126
|
let result = [];
|
|
8099
|
-
for (
|
|
8127
|
+
for (let index = 0; (index < length); (index++)) {
|
|
8100
8128
|
let value = generator(index);
|
|
8101
8129
|
if ((value != null)) {
|
|
8102
8130
|
value = await value;
|
|
@@ -8246,7 +8274,7 @@ export class BallEngine {
|
|
|
8246
8274
|
}
|
|
8247
8275
|
}
|
|
8248
8276
|
if (__ball_eq(objTypeArgs.length, typeArgs.length)) {
|
|
8249
|
-
for (
|
|
8277
|
+
for (let i = 0; (i < typeArgs.length); (i++)) {
|
|
8250
8278
|
if (!__ball_eq(__ball_index(objTypeArgs, i), __ball_index(typeArgs, i))) {
|
|
8251
8279
|
return false;
|
|
8252
8280
|
}
|
|
@@ -8340,7 +8368,7 @@ export class BallEngine {
|
|
|
8340
8368
|
let args = [];
|
|
8341
8369
|
let depth = 0;
|
|
8342
8370
|
let start = 0;
|
|
8343
|
-
for (
|
|
8371
|
+
for (let i = 0; (i < str.length); (i++)) {
|
|
8344
8372
|
if (__ball_eq(__ball_index(str, i), '<')) {
|
|
8345
8373
|
(depth++);
|
|
8346
8374
|
}
|
|
@@ -8577,7 +8605,7 @@ export class BallEngine {
|
|
|
8577
8605
|
if ((!__ball_eq(restIndex, __ball_negate(1)) && (listVal.length < fixedCount))) {
|
|
8578
8606
|
return false;
|
|
8579
8607
|
}
|
|
8580
|
-
for (
|
|
8608
|
+
for (let i = 0; (i < elements.length); (i++)) {
|
|
8581
8609
|
let elem = __ball_index(elements, i);
|
|
8582
8610
|
let elemMap = this._stdAsMap(elem);
|
|
8583
8611
|
if ((!__ball_eq(elemMap, null) && __ball_eq(this._patternKind(elemMap), 'rest'))) {
|
|
@@ -8893,7 +8921,7 @@ export class BallEngine {
|
|
|
8893
8921
|
|
|
8894
8922
|
_repeatString(s: any, count: any): any {
|
|
8895
8923
|
let out = '';
|
|
8896
|
-
for (
|
|
8924
|
+
for (let k = 0; (k < count); (k++)) {
|
|
8897
8925
|
out = (__ball_to_string(out) + __ball_to_string(s));
|
|
8898
8926
|
}
|
|
8899
8927
|
return out;
|
|
@@ -8949,7 +8977,10 @@ export class BallEngine {
|
|
|
8949
8977
|
|
|
8950
8978
|
_stdUnaryNum(input: any, op: any): any {
|
|
8951
8979
|
let value = this._extractUnaryArg(input);
|
|
8952
|
-
|
|
8980
|
+
const __vBD = value instanceof BallDouble;
|
|
8981
|
+
const __result = op(this._toNum(value));
|
|
8982
|
+
if (__vBD && typeof __result === 'number') return new BallDouble(__result);
|
|
8983
|
+
return __result;
|
|
8953
8984
|
}
|
|
8954
8985
|
|
|
8955
8986
|
_stdNot(input: any): any {
|
package/src/engine_setup.ts
CHANGED
|
@@ -231,6 +231,12 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
function _mathAbs(v: any): any {
|
|
234
|
+
// `_coerceInt` unconditionally truncates through int64 coercion (needed
|
|
235
|
+
// for BigInt-magnitude int abs), which silently dropped double-ness for
|
|
236
|
+
// a BallDouble operand — e.g. `(2.5).abs()` returned `2` instead of
|
|
237
|
+
// `2.5` (#115). Route a BallDouble operand through double abs instead.
|
|
238
|
+
const BD = (globalThis as any).BallDouble;
|
|
239
|
+
if (BD && v instanceof BD) return new BD(Math.abs(v.value));
|
|
234
240
|
const coerced = _coerceInt(v);
|
|
235
241
|
if (typeof coerced === 'bigint') {
|
|
236
242
|
return _int64Result(coerced < 0n ? -coerced : coerced);
|
|
@@ -569,6 +575,19 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
569
575
|
case 'ceil': return Math.ceil(self);
|
|
570
576
|
case 'compareTo': return self < arg0 ? -1 : self > arg0 ? 1 : 0;
|
|
571
577
|
case 'clamp': return Math.min(Math.max(self, arg0), arg1);
|
|
578
|
+
case 'remainder': return self % Number(_coerceNum(arg0));
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
// A BallDouble-wrapped receiver (e.g. `double d = 2.5; d.remainder(2)`)
|
|
582
|
+
// falls through every case above (`typeof self !== 'number'`), and the
|
|
583
|
+
// compiled engine's own dispatch calls `self.remainder(...)` — a real
|
|
584
|
+
// method call that doesn't exist on the BallDouble class (unlike
|
|
585
|
+
// floor/ceil/round/abs, which work by accident via Math.* coercing
|
|
586
|
+
// through BallDouble.valueOf()) (#115). Handle it explicitly here.
|
|
587
|
+
{
|
|
588
|
+
const BD = (globalThis as any).BallDouble;
|
|
589
|
+
if (BD && self instanceof BD && fn === 'remainder') {
|
|
590
|
+
return new BD(self.value % Number(_coerceNum(arg0)));
|
|
572
591
|
}
|
|
573
592
|
}
|
|
574
593
|
if (typeof self === 'object' && self !== null && '__type__' in self) {
|
|
@@ -1231,7 +1250,16 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
1231
1250
|
};
|
|
1232
1251
|
|
|
1233
1252
|
e._stdUnaryNum = function(input: any, op: any) {
|
|
1234
|
-
|
|
1253
|
+
// Preserve BallDouble-ness through negate (#67): a whole-number
|
|
1254
|
+
// double like `-7.0` must not collapse to a bare JS integer. Mirrors
|
|
1255
|
+
// the _stdBinary patch above. bitwise_not (the only other consumer)
|
|
1256
|
+
// always operates on int, so it never sees a BallDouble operand here.
|
|
1257
|
+
const value = e._extractUnaryArg(input);
|
|
1258
|
+
const BD = (globalThis as any).BallDouble;
|
|
1259
|
+
const vBD = BD && value instanceof BD;
|
|
1260
|
+
const result = op(_coerceNum(value));
|
|
1261
|
+
if (vBD && typeof result === 'number') return new BD(result);
|
|
1262
|
+
return result;
|
|
1235
1263
|
};
|
|
1236
1264
|
|
|
1237
1265
|
e._stdBinaryComp = function(input: any, op: any) {
|
|
@@ -1264,6 +1292,25 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
1264
1292
|
return result;
|
|
1265
1293
|
};
|
|
1266
1294
|
|
|
1295
|
+
// `remainder` is the one num instance method the compiled engine's own
|
|
1296
|
+
// `_dispatchBuiltinInstanceMethod` calls as a literal Dart method
|
|
1297
|
+
// (`self.remainder(...)`) rather than routing through a Math.*-backed
|
|
1298
|
+
// std function (floor/ceil/round/abs/truncate all get encoder-routed to
|
|
1299
|
+
// math_floor/math_ceil/etc, which is why they survive a BallDouble
|
|
1300
|
+
// receiver via valueOf() coercion). A BallDouble-wrapped receiver has no
|
|
1301
|
+
// `.remainder` method, so it throws (#115). Intercept just that case.
|
|
1302
|
+
const origDispatchBuiltinInstanceMethod = e._dispatchBuiltinInstanceMethod.bind(e);
|
|
1303
|
+
e._dispatchBuiltinInstanceMethod = async function(self: any, method: any, input: any) {
|
|
1304
|
+
const BD = (globalThis as any).BallDouble;
|
|
1305
|
+
if (BD && self instanceof BD && method === 'remainder') {
|
|
1306
|
+
const rec = e._cfAsMap(input) ?? {};
|
|
1307
|
+
const rawArg = rec['arg0'] ?? rec['value'];
|
|
1308
|
+
const other = (BD && rawArg instanceof BD) ? rawArg.value : _coerceNum(rawArg);
|
|
1309
|
+
return new BD(self.value % Number(other));
|
|
1310
|
+
}
|
|
1311
|
+
return origDispatchBuiltinInstanceMethod(self, method, input);
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1267
1314
|
const origPatternKind = e._patternKind?.bind(e);
|
|
1268
1315
|
e._patternKind = function(pattern: any): any {
|
|
1269
1316
|
const explicit = pattern?.['__pattern_kind__'];
|
|
@@ -1669,7 +1716,17 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
1669
1716
|
const rec = e._extractBinaryArgs(i);
|
|
1670
1717
|
return _int64Modulo(rec[0], rec[1]);
|
|
1671
1718
|
});
|
|
1672
|
-
handler.register('negate', (i: any) =>
|
|
1719
|
+
handler.register('negate', (i: any) => {
|
|
1720
|
+
// `_int64Negate` unconditionally coerces through `_coerceInt` (it's
|
|
1721
|
+
// the int64-safe path for `bigint`-magnitude values), which silently
|
|
1722
|
+
// truncated a double operand to an int — losing double-ness for
|
|
1723
|
+
// e.g. `-7.0` (#67). Route a BallDouble operand through double
|
|
1724
|
+
// negation instead; only a genuine int reaches `_int64Negate`.
|
|
1725
|
+
const value = e._extractUnaryArg(i);
|
|
1726
|
+
const BD = (globalThis as any).BallDouble;
|
|
1727
|
+
if (BD && value instanceof BD) return new BD(-value.value);
|
|
1728
|
+
return _int64Negate(value);
|
|
1729
|
+
});
|
|
1673
1730
|
handler.register('bitwise_and', (i: any) => e._stdBinaryInt(i, (a: any, b: any) => _int64Binary((l, r) => l & r, a, b)));
|
|
1674
1731
|
handler.register('bitwise_or', (i: any) => e._stdBinaryInt(i, (a: any, b: any) => _int64Binary((l, r) => l | r, a, b)));
|
|
1675
1732
|
handler.register('bitwise_xor', (i: any) => e._stdBinaryInt(i, (a: any, b: any) => _int64Binary((l, r) => l ^ r, a, b)));
|