@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.
@@ -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
- // Make undefined/null safe for .isEmpty/.isNotEmpty via a global wrapper.
681
- // Proto3 JSON omits empty strings, so code like call.module.isEmpty needs
682
- // to handle undefined gracefully.
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 (var vi = 0; (vi < enumValueList.length); (vi++)) {
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 (var i = 0; (i < params.length); (i++)) {
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 (var i = 0; ((i < params.length) && (i < input.length)); (i++)) {
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 (var i = 0; (i < params.length); (i++)) {
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 (var i = 0; (i < params.length); (i++)) {
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 (var i = 0; (i < argNames.length); (i++)) {
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 (var i = 0; (i < resolvedParams.length); (i++)) {
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 (var i = 0; (i < params.length); (i++)) {
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 (var i = 0; (i < paramNames.length); (i++)) {
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
- do {
5776
- result = await this._evalExpression(body, scope);
5777
- if ((((result instanceof _FlowSignal) && __ball_eq(result.kind, 'goto')) && __ball_eq(result.label, label))) {
5778
- continue;
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
- break;
5781
- } while (true);
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
- unwrappedSelf = self;
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 (var j = 1; (j < sorted.length); (j++)) {
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
- return __ball_to_string(v);
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 (var j = 1; (j < sorted.length); (j++)) {
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 (Array.isArray(r)) {
7033
- __ball_push_all(result, r);
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
- result = (result.push(r), result);
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
- return this._extractField(i, 'value');
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 (var index = 0; (index < length); (index++)) {
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 (var i = 0; (i < typeArgs.length); (i++)) {
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 (var i = 0; (i < str.length); (i++)) {
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 (var i = 0; (i < elements.length); (i++)) {
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 (var k = 0; (k < count); (k++)) {
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
- return op(this._toNum(value));
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 {
@@ -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
- return op(_coerceNum(e._extractUnaryArg(input)));
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) => _int64Negate(e._extractUnaryArg(i)));
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)));