@ball-lang/compiler 1.5.9 → 1.6.1

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.
@@ -49,6 +49,18 @@ export declare class BallCompiler {
49
49
  * the block's statements and pop it afterward.
50
50
  */
51
51
  private renameStack;
52
+ /**
53
+ * Stack of `std.label` names currently enclosing the statement being
54
+ * compiled (see `emitLabelStmt`/`emitGotoStmt`). A `std.label` lowers to a
55
+ * labelled `while (true) { ... break name; }`, and a nested `std.goto`
56
+ * targeting one of these names lowers to `continue name;` — TS (unlike
57
+ * Dart's `continue` targeting a switch case, or C++'s real `goto`) only
58
+ * allows `continue`/`break` to target an *enclosing* labelled loop, so this
59
+ * only supports backward jumps to a label the goto is lexically inside of.
60
+ * A `goto` to any other name fails loud at compile time (see `emitGotoStmt`)
61
+ * rather than silently emitting invalid or wrong-behaving TS.
62
+ */
63
+ private activeGotoLabels;
52
64
  constructor(program: Program);
53
65
  /** Compile to TS source. */
54
66
  compile(options?: CompileOptions): string;
@@ -112,6 +124,19 @@ export declare class BallCompiler {
112
124
  private emitForStmt;
113
125
  private emitForInStmt;
114
126
  private emitWhileStmt;
127
+ /**
128
+ * `std.label(name, body)` — a named jump target that `std.goto(label)`
129
+ * re-enters. TS has no real `goto`, so this lowers to a labelled
130
+ * `while (true)` loop: running the body once and falling off the end
131
+ * (the common case, and the only shape a `goto` targeting it can
132
+ * restart) matches Ball's "run once, or re-run from the top on goto"
133
+ * semantics, with `break name;` after the body covering the fall-off
134
+ * case exactly as the Dart compiler's switch-based simulation does.
135
+ * See `activeGotoLabels` for why only backward jumps are supported.
136
+ */
137
+ private emitLabelStmt;
138
+ /** `std.goto(label)` — see `emitLabelStmt` and `activeGotoLabels`. */
139
+ private emitGotoStmt;
115
140
  private emitDoWhileStmt;
116
141
  private emitTryStmt;
117
142
  private emitAssignStmt;
@@ -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
@@ -58,6 +58,18 @@ export class BallCompiler {
58
58
  * the block's statements and pop it afterward.
59
59
  */
60
60
  renameStack = [];
61
+ /**
62
+ * Stack of `std.label` names currently enclosing the statement being
63
+ * compiled (see `emitLabelStmt`/`emitGotoStmt`). A `std.label` lowers to a
64
+ * labelled `while (true) { ... break name; }`, and a nested `std.goto`
65
+ * targeting one of these names lowers to `continue name;` — TS (unlike
66
+ * Dart's `continue` targeting a switch case, or C++'s real `goto`) only
67
+ * allows `continue`/`break` to target an *enclosing* labelled loop, so this
68
+ * only supports backward jumps to a label the goto is lexically inside of.
69
+ * A `goto` to any other name fails loud at compile time (see `emitGotoStmt`)
70
+ * rather than silently emitting invalid or wrong-behaving TS.
71
+ */
72
+ activeGotoLabels = [];
61
73
  constructor(program) {
62
74
  this.program = program;
63
75
  }
@@ -2688,7 +2700,7 @@ function __isUnknownFnError(e: any): boolean {
2688
2700
  const kinds = new Set([
2689
2701
  "if", "for", "for_in", "for_each", "while", "do_while", "try",
2690
2702
  "return", "break", "continue", "labeled", "throw", "rethrow",
2691
- "assign", "switch", "switch_expr",
2703
+ "assign", "switch", "switch_expr", "label", "goto",
2692
2704
  ]);
2693
2705
  if (!kinds.has(call.function))
2694
2706
  return false;
@@ -2742,6 +2754,12 @@ function __isUnknownFnError(e: any): boolean {
2742
2754
  this.emitStatementOrExpression(body, false);
2743
2755
  break;
2744
2756
  }
2757
+ case "label":
2758
+ this.emitLabelStmt(call);
2759
+ break;
2760
+ case "goto":
2761
+ this.emitGotoStmt(call);
2762
+ break;
2745
2763
  case "throw": {
2746
2764
  const v = field(call, "value");
2747
2765
  if (v) {
@@ -3008,6 +3026,44 @@ function __isUnknownFnError(e: any): boolean {
3008
3026
  this.depth--;
3009
3027
  this.writeln(`}`);
3010
3028
  }
3029
+ /**
3030
+ * `std.label(name, body)` — a named jump target that `std.goto(label)`
3031
+ * re-enters. TS has no real `goto`, so this lowers to a labelled
3032
+ * `while (true)` loop: running the body once and falling off the end
3033
+ * (the common case, and the only shape a `goto` targeting it can
3034
+ * restart) matches Ball's "run once, or re-run from the top on goto"
3035
+ * semantics, with `break name;` after the body covering the fall-off
3036
+ * case exactly as the Dart compiler's switch-based simulation does.
3037
+ * See `activeGotoLabels` for why only backward jumps are supported.
3038
+ */
3039
+ emitLabelStmt(call) {
3040
+ const name = stringField(call, "name");
3041
+ const body = field(call, "body");
3042
+ if (!name || !body) {
3043
+ throw new Error("std.label requires a string \"name\" and a \"body\"");
3044
+ }
3045
+ this.activeGotoLabels.push(name);
3046
+ this.writeln(`${name}: while (true) {`);
3047
+ this.depth++;
3048
+ this.emitStatementOrExpression(body, false);
3049
+ this.writeln(`break ${name};`);
3050
+ this.depth--;
3051
+ this.writeln(`}`);
3052
+ this.activeGotoLabels.pop();
3053
+ }
3054
+ /** `std.goto(label)` — see `emitLabelStmt` and `activeGotoLabels`. */
3055
+ emitGotoStmt(call) {
3056
+ const label = stringField(call, "label");
3057
+ if (!label)
3058
+ throw new Error('std.goto requires a string "label"');
3059
+ if (!this.activeGotoLabels.includes(label)) {
3060
+ throw new Error(`std.goto("${label}") is not inside its own std.label("${label}", ...) body — ` +
3061
+ "the TS compiler only supports goto as a backward jump that restarts an " +
3062
+ "enclosing label (mirrors a labelled loop); forward jumps and jumps to a " +
3063
+ "sibling label are not supported (#226).");
3064
+ }
3065
+ this.writeln(`continue ${label};`);
3066
+ }
3011
3067
  emitDoWhileStmt(call) {
3012
3068
  const cond = field(call, "condition");
3013
3069
  const body = field(call, "body");
@@ -3513,7 +3569,15 @@ function __isUnknownFnError(e: any): boolean {
3513
3569
  this.currentClassName !== undefined &&
3514
3570
  this.currentClassFields.has(fa.field) &&
3515
3571
  !this.currentClassMethodNames.has(fa.field);
3516
- const obj = isSelfRef || isSuperFieldRef ? "this" : this.expr(fa.object);
3572
+ const rawObj = isSelfRef || isSuperFieldRef ? "this" : this.expr(fa.object);
3573
+ // A bare numeric-literal receiver (e.g. `0`, `-4`, `123n`) parses as the
3574
+ // start of a float literal when immediately followed by `.field` —
3575
+ // `0.isNegative` is `SyntaxError: Identifier cannot follow number`.
3576
+ // Parenthesize whenever the compiled object text IS (not merely
3577
+ // contains) such a token; a double literal already compiles through
3578
+ // `new BallDouble(...)` and a negated int through `__ball_negate(...)`,
3579
+ // so both are already safe — only the bare-token case needs this.
3580
+ const obj = /^-?\d+n?$/.test(rawObj) ? `(${rawObj})` : rawObj;
3517
3581
  const f = fa.field;
3518
3582
  if (f === "length")
3519
3583
  return `${obj}.length`;
@@ -3878,7 +3942,7 @@ function __isUnknownFnError(e: any): boolean {
3878
3942
  case "bitwise_not": return `__ball_bitnot(${this.expr(fg("value", "arg0"))})`;
3879
3943
  case "left_shift": return `__ball_shl(${this.expr(fg("left", "value", "arg0"))}, ${this.expr(fg("right", "other", "arg1"))})`;
3880
3944
  case "right_shift": return `__ball_shr(${this.expr(fg("left", "value", "arg0"))}, ${this.expr(fg("right", "other", "arg1"))})`;
3881
- case "unsigned_right_shift": return bin(">>>");
3945
+ case "unsigned_right_shift": return `__ball_ushr(${this.expr(fg("left", "value", "arg0"))}, ${this.expr(fg("right", "other", "arg1"))})`;
3882
3946
  case "integer_divide":
3883
3947
  return `__ball_divide(${this.expr(f.get("left"))}, ${this.expr(f.get("right"))})`;
3884
3948
  case "concat": return bin("+");
@@ -4639,6 +4703,10 @@ function __isUnknownFnError(e: any): boolean {
4639
4703
  case "list_length": return `${this.expr(f.get("list"))}.length`;
4640
4704
  case "list_filter": return `${this.expr(f.get("list"))}.filter(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
4641
4705
  case "list_map": return `${this.expr(f.get("list"))}.map(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
4706
+ // No-seed combine (Dart's Iterable.reduce): starts at the first
4707
+ // element, folds from the second; empty list throws (matches JS
4708
+ // Array.prototype.reduce with no initialValue).
4709
+ case "list_reduce": return `${this.expr(f.get("list"))}.reduce(${this.expr(f.get("function") ?? f.get("callback") ?? f.get("value"))})`;
4642
4710
  case "list_sort": {
4643
4711
  const l = this.expr(f.get("list"));
4644
4712
  const cmp = f.get("comparator") ?? f.get("function") ?? f.get("value");