@ball-lang/compiler 1.7.4 → 1.7.6

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
@@ -4160,8 +4160,14 @@ function __isUnknownFnError(e: any): boolean {
4160
4160
  case "null_aware_call": {
4161
4161
  const target = f.get("target");
4162
4162
  const method = f.get("method");
4163
- if (!target || !method)
4164
- return "/* null_aware_call missing */";
4163
+ // A bare `/* ... */` comment used to stand in for the missing
4164
+ // field context-dependent behavior (silently becomes `undefined`
4165
+ // in return position, a hard-to-diagnose SyntaxError mid-expression)
4166
+ // instead of a clear compile-time error naming the malformed call
4167
+ // (#257).
4168
+ if (!target || !method) {
4169
+ throw new Error("TS compiler: null_aware_call requires a \"target\" and a \"method\" field");
4170
+ }
4165
4171
  const methodName = method.literal?.stringValue ?? "";
4166
4172
  const inputFields = call.input?.messageCreation?.fields ?? [];
4167
4173
  const otherArgs = inputFields
@@ -4173,15 +4179,17 @@ function __isUnknownFnError(e: any): boolean {
4173
4179
  case "null_aware_index": {
4174
4180
  const self_ = f.get("self") ?? f.get("target");
4175
4181
  const idx = f.get("index") ?? f.get("key");
4176
- if (!self_ || !idx)
4177
- return "/* null_aware_index missing */";
4182
+ if (!self_ || !idx) {
4183
+ throw new Error("TS compiler: null_aware_index requires a \"self\"/\"target\" and an \"index\"/\"key\" field");
4184
+ }
4178
4185
  return `${this.expr(self_)}[${this.expr(idx)}]`;
4179
4186
  }
4180
4187
  case "null_aware_access": {
4181
4188
  const target = f.get("target");
4182
4189
  const fieldE = f.get("field");
4183
- if (!target || !fieldE)
4184
- return "/* null_aware_access missing */";
4190
+ if (!target || !fieldE) {
4191
+ throw new Error("TS compiler: null_aware_access requires a \"target\" and a \"field\" field");
4192
+ }
4185
4193
  return `${this.expr(target)}?.${fieldE.literal?.stringValue ?? ""}`;
4186
4194
  }
4187
4195
  case "typed_list": {
@@ -4203,14 +4211,19 @@ function __isUnknownFnError(e: any): boolean {
4203
4211
  return "new Map()";
4204
4212
  const pairs = [];
4205
4213
  for (const e of entryExprs) {
4206
- if (e.messageCreation) {
4207
- const mc = e.messageCreation;
4208
- const mFields = mc.fields ?? [];
4209
- const k = mFields.find((fd) => fd.name === "key")?.value;
4210
- const v = mFields.find((fd) => fd.name === "value")?.value;
4211
- if (k && v)
4212
- pairs.push(`[${this.expr(k)}, ${this.expr(v)}]`);
4214
+ // A malformed entry (not a messageCreation, or missing key/value)
4215
+ // used to be silently dropped from the resulting Map instead of
4216
+ // surfaced fail loud on the malformed IR instead (#257).
4217
+ if (!e.messageCreation) {
4218
+ throw new Error("TS compiler: typed_map entry is not a key/value messageCreation");
4219
+ }
4220
+ const mFields = e.messageCreation.fields ?? [];
4221
+ const k = mFields.find((fd) => fd.name === "key")?.value;
4222
+ const v = mFields.find((fd) => fd.name === "value")?.value;
4223
+ if (!k || !v) {
4224
+ throw new Error("TS compiler: typed_map entry is missing \"key\" or \"value\"");
4213
4225
  }
4226
+ pairs.push(`[${this.expr(k)}, ${this.expr(v)}]`);
4214
4227
  }
4215
4228
  return `new Map([${pairs.join(", ")}])`;
4216
4229
  }
@@ -4567,8 +4580,11 @@ function __isUnknownFnError(e: any): boolean {
4567
4580
  case "map_get": {
4568
4581
  const map = f.get("map");
4569
4582
  const key = f.get("key");
4583
+ // __ball_require_map fails loud on a non-Map instead of silently
4584
+ // returning undefined via bare bracket access (#257, same family
4585
+ // as #218's map_keys/map_values/map_entries).
4570
4586
  if (map && key)
4571
- return `${this.expr(map)}[${this.expr(key)}]`;
4587
+ return `__ball_require_map(${this.expr(map)}, 'map_get')[${this.expr(key)}]`;
4572
4588
  return "undefined";
4573
4589
  }
4574
4590
  case "map_set": {
@@ -4576,49 +4592,62 @@ function __isUnknownFnError(e: any): boolean {
4576
4592
  const key = f.get("key");
4577
4593
  const value = f.get("value");
4578
4594
  if (map && key && value)
4579
- return `(${this.expr(map)}[${this.expr(key)}] = ${this.expr(value)})`;
4595
+ return `(__ball_require_map(${this.expr(map)}, 'map_set')[${this.expr(key)}] = ${this.expr(value)})`;
4580
4596
  return "undefined";
4581
4597
  }
4582
4598
  case "map_contains_key": {
4583
4599
  const map = f.get("map");
4584
4600
  const key = f.get("key");
4601
+ // `in` throws for a primitive receiver already, but not for a List
4602
+ // (checks index membership instead of throwing "not a map") — the
4603
+ // require-map guard closes that gap (#257).
4585
4604
  if (map && key)
4586
- return `(${this.expr(key)} in ${this.expr(map)})`;
4605
+ return `(${this.expr(key)} in __ball_require_map(${this.expr(map)}, 'map_contains_key'))`;
4587
4606
  return "false";
4588
4607
  }
4589
4608
  case "map_keys": {
4590
4609
  const map = f.get("map") ?? f.get("value");
4591
- return map ? `Object.keys(${this.expr(map)})` : "[]";
4610
+ // Fail loud on a non-Map receiver instead of silently returning []
4611
+ // that silent degradation is the class of bug that hid issue #55
4612
+ // (mirrors the .keys DART-GETTER guard already installed in
4613
+ // preamble.ts's defDartGetter block, and the engine/C++-compiler
4614
+ // guards for the same base function, #218).
4615
+ return map ? `__ball_map_keys(${this.expr(map)})` : "[]";
4592
4616
  }
4593
4617
  case "map_values": {
4594
4618
  const map = f.get("map") ?? f.get("value");
4595
- return map ? `Object.values(${this.expr(map)})` : "[]";
4619
+ return map ? `__ball_map_values(${this.expr(map)})` : "[]";
4596
4620
  }
4597
4621
  case "map_entries": {
4598
4622
  const map = f.get("map") ?? f.get("value");
4599
- return map ? `Object.entries(${this.expr(map)}).map(([k, v]) => ({key: k, value: v}))` : "[]";
4623
+ // Same silent-degradation class as map_keys/map_values (#218): a
4624
+ // bare Object.entries(...) on a non-Map silently returns garbage
4625
+ // instead of failing loud.
4626
+ return map ? `__ball_map_entries(${this.expr(map)})` : "[]";
4600
4627
  }
4601
4628
  case "map_length": {
4602
4629
  const map = f.get("map") ?? f.get("value");
4603
- return map ? `Object.keys(${this.expr(map)}).length` : "0";
4630
+ return map ? `Object.keys(__ball_require_map(${this.expr(map)}, 'map_length')).length` : "0";
4604
4631
  }
4605
4632
  case "map_is_empty": {
4606
4633
  const map = f.get("map") ?? f.get("value");
4607
- return map ? `(Object.keys(${this.expr(map)}).length === 0)` : "true";
4634
+ return map ? `(Object.keys(__ball_require_map(${this.expr(map)}, 'map_is_empty')).length === 0)` : "true";
4608
4635
  }
4609
4636
  case "map_delete":
4610
4637
  case "map_remove": {
4611
4638
  const map = f.get("map");
4612
4639
  const key = f.get("key");
4613
4640
  if (map && key)
4614
- return `(() => { const __m = ${this.expr(map)}; const __k = ${this.expr(key)}; const __v = __m[__k]; delete __m[__k]; return __v; })()`;
4641
+ return `(() => { const __m = __ball_require_map(${this.expr(map)}, 'map_delete'); const __k = ${this.expr(key)}; const __v = __m[__k]; delete __m[__k]; return __v; })()`;
4615
4642
  return "undefined";
4616
4643
  }
4617
4644
  case "map_merge": {
4618
4645
  const l = f.get("left") ?? f.get("map");
4619
4646
  const r = f.get("right") ?? f.get("other");
4647
+ // Spreading a non-object silently produces {} (or a partial merge)
4648
+ // instead of throwing — same class as the other map_* guards (#257).
4620
4649
  if (l && r)
4621
- return `{...${this.expr(l)}, ...${this.expr(r)}}`;
4650
+ return `{...__ball_require_map(${this.expr(l)}, 'map_merge'), ...__ball_require_map(${this.expr(r)}, 'map_merge')}`;
4622
4651
  return "{}";
4623
4652
  }
4624
4653
  case "map_from_entries": {
@@ -4636,6 +4665,14 @@ function __isUnknownFnError(e: any): boolean {
4636
4665
  return `${this.expr(list)}.join('')`;
4637
4666
  return "''";
4638
4667
  }
4668
+ // Neither encoder ever emits these as a direct `std.<fn>` base-
4669
+ // function call — a Set method call (mySet.union(other), etc.)
4670
+ // routes through compileCall's generic "self"-field method dispatch
4671
+ // onto native JS Set.prototype methods instead, so this case is
4672
+ // never actually reached. The old fallback compiled it to a call on
4673
+ // a nonexistent bare identifier (a confusing runtime ReferenceError
4674
+ // if it WERE ever hit); fail loud at compile time instead, matching
4675
+ // the policy above (#257).
4639
4676
  case "set_add":
4640
4677
  case "set_remove":
4641
4678
  case "set_contains":
@@ -4644,11 +4681,8 @@ function __isUnknownFnError(e: any): boolean {
4644
4681
  case "set_difference":
4645
4682
  case "set_length":
4646
4683
  case "set_is_empty":
4647
- case "set_to_list": {
4648
- const allFields = call.input?.messageCreation?.fields ?? [];
4649
- const args = allFields.map((fd) => this.expr(fd.value)).join(", ");
4650
- return `/* std.${fn} */ ${sanitize(fn)}(${args})`;
4651
- }
4684
+ case "set_to_list":
4685
+ throw new Error(`TS compiler: std.${fn} is not implemented (compileStdCall) — Set method calls should route through native JS Set methods, not this base function`);
4652
4686
  // I/O
4653
4687
  case "print_error": {
4654
4688
  const msg = f.get("message") ?? f.get("value");
@@ -4757,7 +4791,10 @@ function __isUnknownFnError(e: any): boolean {
4757
4791
  // match first and any duplicate entry here would be genuinely
4758
4792
  // unreachable dead code. Removed (#62 Phase-2c); only cases with
4759
4793
  // no outer-switch equivalent belong in this fallback.
4760
- case "map_contains_value": return `Object.values(${this.expr(f.get("map"))}).includes(${this.expr(f.get("value"))})`;
4794
+ // Same silent-degradation class as map_keys/map_values/map_entries
4795
+ // (#218) — the sibling case that fix missed, since it lives in
4796
+ // this SECOND nested switch under a different function name (#257).
4797
+ case "map_contains_value": return `Object.values(__ball_require_map(${this.expr(f.get("map"))}, 'map_contains_value')).includes(${this.expr(f.get("value"))})`;
4761
4798
  case "list_insert": return `(${this.expr(f.get("list"))}.splice(${this.expr(f.get("index"))}, 0, ${this.expr(f.get("value"))}), ${this.expr(f.get("list"))})`;
4762
4799
  case "list_remove_at": return `${this.expr(f.get("list"))}.splice(${this.expr(f.get("index"))}, 1)[0]`;
4763
4800
  case "list_clear": return `(${this.expr(f.get("list"))}.length = 0, ${this.expr(f.get("list"))})`;
@@ -4785,7 +4822,7 @@ function __isUnknownFnError(e: any): boolean {
4785
4822
  case "map_foreach": {
4786
4823
  const map = this.expr(f.get("map") ?? f.get("value"));
4787
4824
  const cb = this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"));
4788
- return `Object.entries(${map}).forEach(([k, v]) => ${cb}(k, v))`;
4825
+ return `Object.entries(__ball_require_map(${map}, 'map_foreach')).forEach(([k, v]) => ${cb}(k, v))`;
4789
4826
  }
4790
4827
  case "list_reversed": return `[...${this.expr(f.get("list"))}].reverse()`;
4791
4828
  case "compare_to": {
@@ -4852,10 +4889,16 @@ function __isUnknownFnError(e: any): boolean {
4852
4889
  const body = this.emitCollectionElement({ call }, "list", "__r");
4853
4890
  return `(() => { const __r: any[] = []; ${body} return __r; })()`;
4854
4891
  }
4855
- default: {
4856
- const args = Array.from(f.values()).map((e) => this.expr(e)).join(", ");
4857
- return `/* std.${fn} */ ${sanitize(fn)}(${args})`;
4858
- }
4892
+ default:
4893
+ // Fail loud (repo CLAUDE.md): never emit a bare/undefined
4894
+ // identifier for an unimplemented std function — mirrors
4895
+ // compileMemoryCall's rule above. The old
4896
+ // `/* std.${fn} */ ${sanitize(fn)}(${args})` fallback compiled
4897
+ // to a call on a nonexistent identifier, deferring the failure
4898
+ // to a confusing runtime ReferenceError instead of a clear
4899
+ // compile-time error naming the actual unimplemented function
4900
+ // (#257).
4901
+ throw new Error(`TS compiler: std.${fn} is not implemented (compileStdCall)`);
4859
4902
  }
4860
4903
  }
4861
4904
  }