@ball-lang/compiler 1.3.5 → 1.3.7

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.
@@ -61,6 +61,14 @@ export declare class BallCompiler {
61
61
  private wrapIIFE;
62
62
  /** Check if an expression tree references any name in the given set. */
63
63
  private bodyReferencesAny;
64
+ /**
65
+ * Emit a Dart-style enum as a TS class with static singleton instances,
66
+ * `index`/`name` properties, a `values` list, and `toString()` returning
67
+ * `'<Enum>.<member>'`. Shared by the two enum declaration paths:
68
+ * typeDefs with `metadata.kind == "enum"` and `Module.enums[]`
69
+ * (google.protobuf.EnumDescriptorProto) entries.
70
+ */
71
+ private emitEnumClass;
64
72
  private emitClass;
65
73
  private buildCtor;
66
74
  /**
@@ -154,10 +162,11 @@ export declare class BallCompiler {
154
162
  private emitCollectionElement;
155
163
  /**
156
164
  * Render a C-style for-init `block` (a single-let, no-result block) as an
157
- * inline declaration string like `var i = 0` — NOT an IIFE, so the loop
165
+ * inline declaration string like `let i = 0` — NOT an IIFE, so the loop
158
166
  * variable stays in scope for the condition/update. Mirrors the Dart
159
- * compiler's `_renderForInit`. Uses `var` to match Dart's shared-variable
160
- * loop-capture semantics. Returns "" on an unrecognized shape.
167
+ * compiler's `_renderForInit`. Uses `let` so each iteration gets its own
168
+ * binding, matching Dart's per-iteration loop-variable capture semantics
169
+ * (#69, conformance 312). Returns "" on an unrecognized shape.
161
170
  */
162
171
  private renderForInit;
163
172
  private compileFieldAccess;
@@ -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
@@ -162,6 +162,26 @@ export class BallCompiler {
162
162
  }
163
163
  this.emitClass(sf, td, members);
164
164
  }
165
+ // Enums declared in Module.enums[] (google.protobuf.EnumDescriptorProto,
166
+ // proto3 JSON: `{name, value: [{name, number}]}`). Both encoders emit
167
+ // enum declarations here (the Dart encoder with module-qualified names
168
+ // like "main:Color"); dropping them left `Color.red` references dangling
169
+ // in the compiled output (#120).
170
+ const emittedTypeNames = new Set(allTypeDefs.map((td) => classTsName(td.name)));
171
+ for (const mod of userModules) {
172
+ for (const en of mod.enums ?? []) {
173
+ const tsName = classTsName(en.name);
174
+ // A typeDef of the same name already produced a class declaration.
175
+ if (emittedTypeNames.has(tsName))
176
+ continue;
177
+ emittedTypeNames.add(tsName);
178
+ const entries = (en.value ?? []).map((v, i) => ({
179
+ name: v.name,
180
+ index: typeof v.number === "number" ? v.number : i,
181
+ }));
182
+ this.emitEnumClass(sf, tsName, entries);
183
+ }
184
+ }
165
185
  // Top-level variables (kind == 'top_level_variable') emit as
166
186
  // `const <name> = <body>;` before free functions.
167
187
  for (const fn of freeFunctions.filter((f) => f.metadata?.kind === "top_level_variable")) {
@@ -1969,17 +1989,17 @@ function __isUnknownFnError(e: any): boolean {
1969
1989
  return true;
1970
1990
  return false;
1971
1991
  }
1972
- emitClass(sf, td, members) {
1973
- const meta = td.metadata ?? {};
1974
- const tsName = classTsName(td.name);
1975
- // Enum handling: emit a class with static instances, index, name, values.
1976
- if (meta["kind"] === "enum") {
1977
- const enumValues = Array.isArray(meta["values"]) ? meta["values"] : [];
1978
- const valueNames = enumValues.map((v) => typeof v === "string" ? v : (v?.name ?? ""));
1979
- // Build the enum class with index, name, static instances, and values.
1980
- const staticProps = valueNames.map((name, i) => `static readonly ${sanitize(name)} = new ${tsName}(${i}, '${name}');`);
1981
- const valuesArray = valueNames.map((name) => `${tsName}.${sanitize(name)}`).join(", ");
1982
- sf.addStatements(`export class ${tsName} {
1992
+ /**
1993
+ * Emit a Dart-style enum as a TS class with static singleton instances,
1994
+ * `index`/`name` properties, a `values` list, and `toString()` returning
1995
+ * `'<Enum>.<member>'`. Shared by the two enum declaration paths:
1996
+ * typeDefs with `metadata.kind == "enum"` and `Module.enums[]`
1997
+ * (google.protobuf.EnumDescriptorProto) entries.
1998
+ */
1999
+ emitEnumClass(sf, tsName, entries) {
2000
+ const staticProps = entries.map((e) => `static readonly ${sanitize(e.name)} = new ${tsName}(${e.index}, '${e.name}');`);
2001
+ const valuesArray = entries.map((e) => `${tsName}.${sanitize(e.name)}`).join(", ");
2002
+ sf.addStatements(`export class ${tsName} {
1983
2003
  readonly index: number;
1984
2004
  readonly name: string;
1985
2005
  private constructor(index: number, name: string) { this.index = index; this.name = name; }
@@ -1987,6 +2007,18 @@ function __isUnknownFnError(e: any): boolean {
1987
2007
  static readonly values: ${tsName}[] = [${valuesArray}];
1988
2008
  toString(): string { return '${tsName}.' + this.name; }
1989
2009
  }`);
2010
+ }
2011
+ emitClass(sf, td, members) {
2012
+ const meta = td.metadata ?? {};
2013
+ const tsName = classTsName(td.name);
2014
+ // Enum handling: emit a class with static instances, index, name, values.
2015
+ if (meta["kind"] === "enum") {
2016
+ const enumValues = Array.isArray(meta["values"]) ? meta["values"] : [];
2017
+ const entries = enumValues.map((v, i) => ({
2018
+ name: typeof v === "string" ? v : (v?.name ?? ""),
2019
+ index: i,
2020
+ }));
2021
+ this.emitEnumClass(sf, tsName, entries);
1990
2022
  return;
1991
2023
  }
1992
2024
  // Fields: prefer metadata.fields (richer) with descriptor fallback.
@@ -2883,10 +2915,12 @@ function __isUnknownFnError(e: any): boolean {
2883
2915
  const start = field(call, "start");
2884
2916
  let initStr;
2885
2917
  if (variable && start) {
2886
- // Use `var` (not `let`) to match Dart's shared-variable loop semantics.
2887
- // Dart closures in loops capture the shared variable (final value);
2888
- // JS `let` gives per-iteration copies which breaks this behavior.
2889
- initStr = `var ${variable} = ${this.expr(start)}`;
2918
+ // Use `let` for a per-iteration binding: Dart's C-style for loop gives
2919
+ // each iteration its OWN copy of the loop variable, so closures created
2920
+ // in the body capture that iteration's value (conformance 229/312).
2921
+ // JS `let` matches this exactly; `var` would share one binding and
2922
+ // leak the final value into every closure (#69).
2923
+ initStr = `let ${variable} = ${this.expr(start)}`;
2890
2924
  }
2891
2925
  else if (init && init.literal?.stringValue !== undefined) {
2892
2926
  initStr = translateInitString(init.literal.stringValue);
@@ -2907,7 +2941,7 @@ function __isUnknownFnError(e: any): boolean {
2907
2941
  }
2908
2942
  }
2909
2943
  }
2910
- initStr = parts.length > 0 ? `var ${parts.join(", ")}` : "";
2944
+ initStr = parts.length > 0 ? `let ${parts.join(", ")}` : "";
2911
2945
  }
2912
2946
  else if (init) {
2913
2947
  initStr = this.expr(init);
@@ -3406,10 +3440,11 @@ function __isUnknownFnError(e: any): boolean {
3406
3440
  }
3407
3441
  /**
3408
3442
  * Render a C-style for-init `block` (a single-let, no-result block) as an
3409
- * inline declaration string like `var i = 0` — NOT an IIFE, so the loop
3443
+ * inline declaration string like `let i = 0` — NOT an IIFE, so the loop
3410
3444
  * variable stays in scope for the condition/update. Mirrors the Dart
3411
- * compiler's `_renderForInit`. Uses `var` to match Dart's shared-variable
3412
- * loop-capture semantics. Returns "" on an unrecognized shape.
3445
+ * compiler's `_renderForInit`. Uses `let` so each iteration gets its own
3446
+ * binding, matching Dart's per-iteration loop-variable capture semantics
3447
+ * (#69, conformance 312). Returns "" on an unrecognized shape.
3413
3448
  */
3414
3449
  renderForInit(initExpr) {
3415
3450
  const block = initExpr.block;
@@ -3431,7 +3466,7 @@ function __isUnknownFnError(e: any): boolean {
3431
3466
  bindings.push(name);
3432
3467
  }
3433
3468
  }
3434
- return bindings.length > 0 ? `var ${bindings.join(", ")}` : "";
3469
+ return bindings.length > 0 ? `let ${bindings.join(", ")}` : "";
3435
3470
  }
3436
3471
  compileFieldAccess(fa) {
3437
3472
  // Ball's `self.field` in class methods → `this.field` in JS.