@ball-lang/compiler 1.59.9 → 1.59.11

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":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
package/dist/compiler.js CHANGED
@@ -3478,6 +3478,19 @@ function __isUnknownFnError(e: any): boolean {
3478
3478
  if (t && idx)
3479
3479
  return `${this.expr(t)}[${this.expr(idx)}]`;
3480
3480
  }
3481
+ // `null_aware_index` in ASSIGNMENT-TARGET position must be a plain `[…]`:
3482
+ // `a?.[i] = v` is a SyntaxError ("the left-hand side of an assignment
3483
+ // expression must be a variable or a property access"), which is why the
3484
+ // read path emitting `?.[` alone broke the whole self-hosted engine. Dart's
3485
+ // `a?[i] = v` short-circuits when `a` is null; JS has no such form, so the
3486
+ // plain index is the closest faithful lowering for the write path.
3487
+ if (c && (c.function === "null_aware_index") &&
3488
+ (c.module === "" || c.module === "std")) {
3489
+ const t = field(c, "self") ?? field(c, "target");
3490
+ const idx = field(c, "index") ?? field(c, "key");
3491
+ if (t && idx)
3492
+ return `${this.expr(t)}[${this.expr(idx)}]`;
3493
+ }
3481
3494
  return this.expr(e);
3482
3495
  }
3483
3496
  typedCatchCondition(type) {
@@ -4404,7 +4417,13 @@ function __isUnknownFnError(e: any): boolean {
4404
4417
  if (!self_ || !idx) {
4405
4418
  throw new Error("TS compiler: null_aware_index requires a \"self\"/\"target\" and an \"index\"/\"key\" field");
4406
4419
  }
4407
- return `${this.expr(self_)}[${this.expr(idx)}]`;
4420
+ // `?.[` — NOT a plain `[`. Emitting `target[index]` threw
4421
+ // "Cannot read properties of null" for exactly the null receiver the
4422
+ // construct exists to guard against, which is the opposite of what
4423
+ // `a?.[i]` means. Caught by the optional-element-access round-trip
4424
+ // fixture added with #489 (no encoder emitted this shape before, so
4425
+ // nothing had ever executed it).
4426
+ return `${this.expr(self_)}?.[${this.expr(idx)}]`;
4408
4427
  }
4409
4428
  case "null_aware_access": {
4410
4429
  const target = f.get("target");
@@ -4661,6 +4680,23 @@ function __isUnknownFnError(e: any): boolean {
4661
4680
  return `${this.expr(v)}.replace(${this.expr(from)}, ${this.expr(to)})`;
4662
4681
  return "''";
4663
4682
  }
4683
+ // ── Regex (std) ───────────────────────────────────────────────────
4684
+ // Field shapes mirror the Dart reference engine exactly
4685
+ // (dart/engine/lib/engine_std.dart): match/find/find_all take
4686
+ // left = subject, right = pattern; replace/replace_all take
4687
+ // value/from/to. The pattern is always a plain string — the std regex
4688
+ // functions model no flags, so the TS encoder reports a dropped flag as
4689
+ // a behaviour-affecting warning rather than encoding it (#490).
4690
+ case "regex_match":
4691
+ return `new RegExp(${this.expr(fg("right", "pattern", "arg1"))}).test(${this.expr(fg("left", "value", "arg0"))})`;
4692
+ case "regex_find":
4693
+ return `(${this.expr(fg("left", "value", "arg0"))}.match(new RegExp(${this.expr(fg("right", "pattern", "arg1"))})) ?? [null])[0]`;
4694
+ case "regex_find_all":
4695
+ return `(${this.expr(fg("left", "value", "arg0"))}.match(new RegExp(${this.expr(fg("right", "pattern", "arg1"))}, 'g')) ?? [])`;
4696
+ case "regex_replace":
4697
+ return `${this.expr(f.get("value"))}.replace(new RegExp(${this.expr(f.get("from"))}), ${this.expr(f.get("to"))})`;
4698
+ case "regex_replace_all":
4699
+ return `${this.expr(f.get("value"))}.replace(new RegExp(${this.expr(f.get("from"))}, 'g'), ${this.expr(f.get("to"))})`;
4664
4700
  case "string_replace_all": {
4665
4701
  const v = f.get("value") ?? f.get("string");
4666
4702
  const from = f.get("from") ?? f.get("pattern");
@@ -5039,6 +5075,11 @@ function __isUnknownFnError(e: any): boolean {
5039
5075
  }
5040
5076
  case "list_any": return `${this.expr(f.get("list"))}.some(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
5041
5077
  case "list_all": return `${this.expr(f.get("list"))}.every(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
5078
+ // Dart's Iterable.firstWhere / JS Array.find. Declared in
5079
+ // dart/shared/lib/std_collections.dart and implemented by the Dart
5080
+ // engine, but never reachable from TS before (#489).
5081
+ case "list_find": return `${this.expr(f.get("list"))}.find(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
5082
+ case "list_flat_map": return `${this.expr(f.get("list"))}.flatMap(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
5042
5083
  case "list_to_list": return `[...${this.expr(f.get("list"))}]`;
5043
5084
  case "list_foreach": return `${this.expr(f.get("list"))}.forEach(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
5044
5085
  case "map_foreach": {
@@ -5375,6 +5416,10 @@ function __isUnknownFnError(e: any): boolean {
5375
5416
  const subjectStr = this.expr(subjectExpr);
5376
5417
  const caseExprs = casesField.literal?.listValue?.elements ?? [];
5377
5418
  let defaultBody;
5419
+ // Tracked separately from `defaultBody`: a `default:` arm that carries no
5420
+ // body still CATCHES (it just evaluates to nothing), so it is not a
5421
+ // non-exhaustive switch. Only "no default arm at all" is.
5422
+ let hasDefault = false;
5378
5423
  // Each branch carries its match condition, the pattern's bindings, the
5379
5424
  // body expression and an optional `when` guard. The guard references the
5380
5425
  // bound variables, so it must be evaluated where those bindings are in
@@ -5407,6 +5452,7 @@ function __isUnknownFnError(e: any): boolean {
5407
5452
  // Check for is_default flag
5408
5453
  if (isDefaultFlag) {
5409
5454
  defaultBody = body;
5455
+ hasDefault = true;
5410
5456
  continue;
5411
5457
  }
5412
5458
  if (!body)
@@ -5419,6 +5465,7 @@ function __isUnknownFnError(e: any): boolean {
5419
5465
  // refutable branch (the guard can still fall through).
5420
5466
  if (result.condition === "true" && result.bindings.length === 0 && !guardField) {
5421
5467
  defaultBody = body;
5468
+ hasDefault = true;
5422
5469
  break;
5423
5470
  }
5424
5471
  branches.push({ cond: result.condition, bindings: result.bindings, body, guard: guardField });
@@ -5432,6 +5479,7 @@ function __isUnknownFnError(e: any): boolean {
5432
5479
  const caseMatch = pattern ?? valueField;
5433
5480
  if (!caseMatch) {
5434
5481
  defaultBody = body;
5482
+ hasDefault = true;
5435
5483
  continue;
5436
5484
  }
5437
5485
  const patText = patternLiteralText(caseMatch);
@@ -5447,13 +5495,41 @@ function __isUnknownFnError(e: any): boolean {
5447
5495
  const cond = patternToTsCondition(patText, subjectStr);
5448
5496
  if (cond === "true" && !guardField) {
5449
5497
  defaultBody = body;
5498
+ hasDefault = true;
5450
5499
  break;
5451
5500
  }
5452
5501
  // Check if the pattern introduces variable bindings.
5453
5502
  const bindings = patternBindings(patText, subjectStr);
5454
5503
  branches.push({ cond, bindings, body, guard: guardField });
5455
5504
  }
5456
- const tail = defaultBody ? this.expr(defaultBody) : "undefined";
5505
+ // What the switch evaluates to when nothing matched.
5506
+ //
5507
+ // A defaultless switch EXPRESSION that matched nothing is non-exhaustive.
5508
+ // Dart's engine throws BallRuntimeError('Non-exhaustive switch expression')
5509
+ // (dart/engine/lib/engine_control_flow.dart), C# throws
5510
+ // BallRuntimeException with the same text (csharp/compiler/src/BaseCall.cs),
5511
+ // and Go/Rust throw it too (issue #467). TypeScript answered `undefined`
5512
+ // instead — a silent wrong value where every other target fails loud, and
5513
+ // exactly the silent-degradation shape CLAUDE.md's fail-loud rule forbids.
5514
+ //
5515
+ // Two guards keep this faithful, both mirroring the Rust port:
5516
+ // - only a switch EXPRESSION throws. A statement `switch` legally does
5517
+ // nothing when no case matches, so it still yields `undefined`.
5518
+ // - only "no `default` arm AT ALL" is non-exhaustive; a `default:` that
5519
+ // carries no body still catches.
5520
+ //
5521
+ // Engine-safety: the self-hosted engine's own oneof dispatchers
5522
+ // (`_evalExpression` on whichExpr, `_evalLiteral` on whichValue) are
5523
+ // defaultless switch expressions, but each carries an explicit `notSet`
5524
+ // arm, so this tail is unreachable there. Measured, not assumed —
5525
+ // engine_runtime.test.ts runs the whole conformance corpus through the
5526
+ // engine compiled by THIS compiler.
5527
+ const nonExhaustive = call.function === "switch_expr" && !hasDefault;
5528
+ const tail = defaultBody
5529
+ ? this.expr(defaultBody)
5530
+ : nonExhaustive
5531
+ ? "(() => { throw 'Non-exhaustive switch expression'; })()"
5532
+ : "undefined";
5457
5533
  if (branches.length === 0)
5458
5534
  return tail;
5459
5535
  let result = tail;