@ball-lang/compiler 1.6.3 → 1.7.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,QA+4C/B,CAAC"}
1
+ {"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,QAq7C/B,CAAC"}
package/dist/preamble.js CHANGED
@@ -378,31 +378,77 @@ function __ball_push_all(target: any, items: any): void {
378
378
  // demotes back to Number when the result fits in MAX_SAFE_INTEGER.
379
379
  const __I64_MAX = 9223372036854775807n;
380
380
  const __I64_MIN = -9223372036854775808n;
381
- const __I64_MOD = 18446744073709551616n;
382
381
  function __i64_wrap(v: bigint): any {
383
- v = ((v % __I64_MOD) + __I64_MOD) % __I64_MOD;
384
- if (v > __I64_MAX) v = v - __I64_MOD;
382
+ // Two's-complement wrap to the signed 64-bit range — BigInt.asIntN(64, v)
383
+ // is the idiomatic builtin for exactly this (equivalent to the old manual
384
+ // modulo-then-resign, verified against it across boundary/overflow cases).
385
+ v = BigInt.asIntN(64, v);
385
386
  if (v >= -9007199254740991n && v <= 9007199254740991n) return Number(v);
386
387
  return v;
387
388
  }
388
389
  function __to_bigint(v: any): bigint {
389
390
  if (typeof v === 'bigint') return v;
391
+ // Matches the reference Dart engine's _toInt (engine_std.dart), which
392
+ // falls through to 0 for anything that isn't an int/BallInt/double/
393
+ // BallDouble/String/bool -- including null. NaN is deliberately NOT
394
+ // special-cased here: Dart's double.toInt() throws on NaN (via
395
+ // _ballDoubleToInt64), and BigInt(NaN) already throws for the same
396
+ // reason (RangeError: not an integer), so that path already fails loud
397
+ // consistently with the reference engine without any extra handling.
398
+ if (v === null || v === undefined) return 0n;
390
399
  if (v instanceof BallDouble) return BigInt(Math.trunc(v.value));
391
400
  return BigInt(v);
392
401
  }
393
- function __ball_bitand(a: any, b: any): any { return __i64_wrap(__to_bigint(a) & __to_bigint(b)); }
394
- function __ball_bitor(a: any, b: any): any { return __i64_wrap(__to_bigint(a) | __to_bigint(b)); }
395
- function __ball_bitxor(a: any, b: any): any { return __i64_wrap(__to_bigint(a) ^ __to_bigint(b)); }
396
- function __ball_bitnot(a: any): any { return __i64_wrap(~__to_bigint(a)); }
402
+ // Fast-path guard: true when v is a plain (non-bigint, non-BallDouble)
403
+ // integer within the signed 32-bit range. AND/OR/XOR/NOT never grow a
404
+ // result past its operands' bit width, so when both operands fit in 32
405
+ // bits, JS's native 32-bit bitwise operators give a result numerically
406
+ // IDENTICAL to the full 64-bit BigInt path (sign-extending a 32-bit value
407
+ // to 64 bits before AND/OR/XOR/NOT never changes the low 32 result bits,
408
+ // and — verified across the full boundary range — never changes whether
409
+ // the high bits are the correct sign-extension of them either). Left/right
410
+ // shift are NOT given this fast path: shifting can grow a result past 32
411
+ // bits even when the input operand fits (e.g. large_int << 40), so their
412
+ // overflow behavior isn't safely 32-bit-local the way AND/OR/XOR/NOT is.
413
+ function __fits32(v: any): boolean {
414
+ return typeof v === 'number' && Number.isInteger(v) && v >= -2147483648 && v <= 2147483647;
415
+ }
416
+ function __ball_bitand(a: any, b: any): any {
417
+ if (__fits32(a) && __fits32(b)) return a & b;
418
+ return __i64_wrap(__to_bigint(a) & __to_bigint(b));
419
+ }
420
+ function __ball_bitor(a: any, b: any): any {
421
+ if (__fits32(a) && __fits32(b)) return a | b;
422
+ return __i64_wrap(__to_bigint(a) | __to_bigint(b));
423
+ }
424
+ function __ball_bitxor(a: any, b: any): any {
425
+ if (__fits32(a) && __fits32(b)) return a ^ b;
426
+ return __i64_wrap(__to_bigint(a) ^ __to_bigint(b));
427
+ }
428
+ function __ball_bitnot(a: any): any {
429
+ if (__fits32(a)) return ~a;
430
+ return __i64_wrap(~__to_bigint(a));
431
+ }
397
432
  function __ball_shl(a: any, b: any): any { return __i64_wrap(__to_bigint(a) << __to_bigint(b)); }
398
433
  function __ball_shr(a: any, b: any): any { return __i64_wrap(__to_bigint(a) >> __to_bigint(b)); }
399
434
  // Unsigned/logical shift: reinterpret a as an unsigned 64-bit value (add
400
435
  // 2^64 if negative) before shifting, so zeros fill from the left instead of
401
436
  // the sign bit — unlike >>> on raw JS numbers, which is only 32-bit.
402
437
  function __ball_ushr(a: any, b: any): any {
403
- const unsigned = ((__to_bigint(a) % __I64_MOD) + __I64_MOD) % __I64_MOD;
438
+ const unsigned = BigInt.asUintN(64, __to_bigint(a));
404
439
  return __i64_wrap(unsigned >> __to_bigint(b));
405
440
  }
441
+ // json_encode (dart:convert's jsonEncode) on a bigint-range int64 must not
442
+ // crash -- JSON.stringify throws "Do not know how to serialize a BigInt"
443
+ // without a toJSON. This is NOT proto3-JSON (which quotes int64 as a
444
+ // string) -- Ball's dart:convert-style jsonEncode matches Dart's own
445
+ // dart:convert (a bare, unquoted JSON number) and the C++ self-host's
446
+ // _ball_json_encode (std::to_string(int64_t), also unquoted). JSON.rawJSON
447
+ // embeds the exact decimal digits as a raw number token, avoiding the
448
+ // precision loss Number(this) would introduce for values past 2^53.
449
+ (BigInt.prototype as any).toJSON = function (this: bigint) {
450
+ return (JSON as any).rawJSON(this.toString());
451
+ };
406
452
  function __ball_negate(a: any): any {
407
453
  if (typeof a === 'bigint') return __i64_wrap(-a);
408
454
  if (a instanceof BallDouble) return new BallDouble(-a.value);
@@ -466,14 +512,6 @@ function __dart_mod(a: any, b: any): any {
466
512
  // Active exception for rethrow. Catch bodies shadow with a local.
467
513
  let __ball_active_error: any = undefined;
468
514
 
469
- // Safe own-property lookup. Returns undefined if key is not an own property.
470
- // Avoids triggering Object.prototype getters (entries, keys, values) on
471
- // plain objects that aren't meant to be Dart Maps.
472
- function __ball_own(obj: any, key: any): any {
473
- if (obj == null || typeof obj !== 'object') return undefined;
474
- return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
475
- }
476
-
477
515
  // Dart-style index access. Dart's List '[]' operator throws RangeError on
478
516
  // out-of-bounds access, whereas JS array indexing silently returns undefined.
479
517
  // To make 'on RangeError' catch clauses behave like Dart we bounds-check list
@@ -1 +1 @@
1
- {"version":3,"file":"preamble.js","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+4C5C,CAAC"}
1
+ {"version":3,"file":"preamble.js","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAq7C5C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ball-lang/compiler",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "description": "Ball → TypeScript compiler. Consumes a Ball protobuf Program and emits idiomatic TypeScript via ts-morph. The canonical TS compiler for Ball — lives in TS land so TS syntax knowledge doesn't leak into other languages.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/preamble.ts CHANGED
@@ -378,31 +378,77 @@ function __ball_push_all(target: any, items: any): void {
378
378
  // demotes back to Number when the result fits in MAX_SAFE_INTEGER.
379
379
  const __I64_MAX = 9223372036854775807n;
380
380
  const __I64_MIN = -9223372036854775808n;
381
- const __I64_MOD = 18446744073709551616n;
382
381
  function __i64_wrap(v: bigint): any {
383
- v = ((v % __I64_MOD) + __I64_MOD) % __I64_MOD;
384
- if (v > __I64_MAX) v = v - __I64_MOD;
382
+ // Two's-complement wrap to the signed 64-bit range — BigInt.asIntN(64, v)
383
+ // is the idiomatic builtin for exactly this (equivalent to the old manual
384
+ // modulo-then-resign, verified against it across boundary/overflow cases).
385
+ v = BigInt.asIntN(64, v);
385
386
  if (v >= -9007199254740991n && v <= 9007199254740991n) return Number(v);
386
387
  return v;
387
388
  }
388
389
  function __to_bigint(v: any): bigint {
389
390
  if (typeof v === 'bigint') return v;
391
+ // Matches the reference Dart engine's _toInt (engine_std.dart), which
392
+ // falls through to 0 for anything that isn't an int/BallInt/double/
393
+ // BallDouble/String/bool -- including null. NaN is deliberately NOT
394
+ // special-cased here: Dart's double.toInt() throws on NaN (via
395
+ // _ballDoubleToInt64), and BigInt(NaN) already throws for the same
396
+ // reason (RangeError: not an integer), so that path already fails loud
397
+ // consistently with the reference engine without any extra handling.
398
+ if (v === null || v === undefined) return 0n;
390
399
  if (v instanceof BallDouble) return BigInt(Math.trunc(v.value));
391
400
  return BigInt(v);
392
401
  }
393
- function __ball_bitand(a: any, b: any): any { return __i64_wrap(__to_bigint(a) & __to_bigint(b)); }
394
- function __ball_bitor(a: any, b: any): any { return __i64_wrap(__to_bigint(a) | __to_bigint(b)); }
395
- function __ball_bitxor(a: any, b: any): any { return __i64_wrap(__to_bigint(a) ^ __to_bigint(b)); }
396
- function __ball_bitnot(a: any): any { return __i64_wrap(~__to_bigint(a)); }
402
+ // Fast-path guard: true when v is a plain (non-bigint, non-BallDouble)
403
+ // integer within the signed 32-bit range. AND/OR/XOR/NOT never grow a
404
+ // result past its operands' bit width, so when both operands fit in 32
405
+ // bits, JS's native 32-bit bitwise operators give a result numerically
406
+ // IDENTICAL to the full 64-bit BigInt path (sign-extending a 32-bit value
407
+ // to 64 bits before AND/OR/XOR/NOT never changes the low 32 result bits,
408
+ // and — verified across the full boundary range — never changes whether
409
+ // the high bits are the correct sign-extension of them either). Left/right
410
+ // shift are NOT given this fast path: shifting can grow a result past 32
411
+ // bits even when the input operand fits (e.g. large_int << 40), so their
412
+ // overflow behavior isn't safely 32-bit-local the way AND/OR/XOR/NOT is.
413
+ function __fits32(v: any): boolean {
414
+ return typeof v === 'number' && Number.isInteger(v) && v >= -2147483648 && v <= 2147483647;
415
+ }
416
+ function __ball_bitand(a: any, b: any): any {
417
+ if (__fits32(a) && __fits32(b)) return a & b;
418
+ return __i64_wrap(__to_bigint(a) & __to_bigint(b));
419
+ }
420
+ function __ball_bitor(a: any, b: any): any {
421
+ if (__fits32(a) && __fits32(b)) return a | b;
422
+ return __i64_wrap(__to_bigint(a) | __to_bigint(b));
423
+ }
424
+ function __ball_bitxor(a: any, b: any): any {
425
+ if (__fits32(a) && __fits32(b)) return a ^ b;
426
+ return __i64_wrap(__to_bigint(a) ^ __to_bigint(b));
427
+ }
428
+ function __ball_bitnot(a: any): any {
429
+ if (__fits32(a)) return ~a;
430
+ return __i64_wrap(~__to_bigint(a));
431
+ }
397
432
  function __ball_shl(a: any, b: any): any { return __i64_wrap(__to_bigint(a) << __to_bigint(b)); }
398
433
  function __ball_shr(a: any, b: any): any { return __i64_wrap(__to_bigint(a) >> __to_bigint(b)); }
399
434
  // Unsigned/logical shift: reinterpret a as an unsigned 64-bit value (add
400
435
  // 2^64 if negative) before shifting, so zeros fill from the left instead of
401
436
  // the sign bit — unlike >>> on raw JS numbers, which is only 32-bit.
402
437
  function __ball_ushr(a: any, b: any): any {
403
- const unsigned = ((__to_bigint(a) % __I64_MOD) + __I64_MOD) % __I64_MOD;
438
+ const unsigned = BigInt.asUintN(64, __to_bigint(a));
404
439
  return __i64_wrap(unsigned >> __to_bigint(b));
405
440
  }
441
+ // json_encode (dart:convert's jsonEncode) on a bigint-range int64 must not
442
+ // crash -- JSON.stringify throws "Do not know how to serialize a BigInt"
443
+ // without a toJSON. This is NOT proto3-JSON (which quotes int64 as a
444
+ // string) -- Ball's dart:convert-style jsonEncode matches Dart's own
445
+ // dart:convert (a bare, unquoted JSON number) and the C++ self-host's
446
+ // _ball_json_encode (std::to_string(int64_t), also unquoted). JSON.rawJSON
447
+ // embeds the exact decimal digits as a raw number token, avoiding the
448
+ // precision loss Number(this) would introduce for values past 2^53.
449
+ (BigInt.prototype as any).toJSON = function (this: bigint) {
450
+ return (JSON as any).rawJSON(this.toString());
451
+ };
406
452
  function __ball_negate(a: any): any {
407
453
  if (typeof a === 'bigint') return __i64_wrap(-a);
408
454
  if (a instanceof BallDouble) return new BallDouble(-a.value);
@@ -466,14 +512,6 @@ function __dart_mod(a: any, b: any): any {
466
512
  // Active exception for rethrow. Catch bodies shadow with a local.
467
513
  let __ball_active_error: any = undefined;
468
514
 
469
- // Safe own-property lookup. Returns undefined if key is not an own property.
470
- // Avoids triggering Object.prototype getters (entries, keys, values) on
471
- // plain objects that aren't meant to be Dart Maps.
472
- function __ball_own(obj: any, key: any): any {
473
- if (obj == null || typeof obj !== 'object') return undefined;
474
- return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
475
- }
476
-
477
515
  // Dart-style index access. Dart's List '[]' operator throws RangeError on
478
516
  // out-of-bounds access, whereas JS array indexing silently returns undefined.
479
517
  // To make 'on RangeError' catch clauses behave like Dart we bounds-check list