@ball-lang/compiler 1.7.3 → 1.7.5
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.
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +62 -4
- package/dist/compiler.js.map +1 -1
- package/dist/preamble.d.ts.map +1 -1
- package/dist/preamble.js +46 -8
- package/dist/preamble.js.map +1 -1
- package/package.json +1 -1
- package/src/compiler.ts +62 -4
- package/src/preamble.ts +46 -8
package/dist/preamble.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../src/preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,QA29C/B,CAAC"}
|
package/dist/preamble.js
CHANGED
|
@@ -994,14 +994,11 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
994
994
|
},
|
|
995
995
|
});
|
|
996
996
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
// .keys/.values on a non-Map must FAIL LOUD (throw a catchable error), not
|
|
1003
|
-
// silently return [] — the silent-degradation class of bug that hid issue
|
|
1004
|
-
// #55 (mirrors the fix already applied to the Dart/C++ compilers).
|
|
997
|
+
// .entries/.keys/.values on a non-Map must FAIL LOUD (throw a catchable
|
|
998
|
+
// error), not silently return [] — the silent-degradation class of bug
|
|
999
|
+
// that hid issue #55 (mirrors the fix already applied to the Dart/C++
|
|
1000
|
+
// compilers). .entries used to be the odd one out here, silently
|
|
1001
|
+
// returning [] instead of throwing — same bug family as #218.
|
|
1005
1002
|
//
|
|
1006
1003
|
// A getter installed on Object.prototype is invoked in "sloppy" (non-strict)
|
|
1007
1004
|
// script contexts with this auto-boxed to a Number/String/Boolean WRAPPER
|
|
@@ -1014,6 +1011,13 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
1014
1011
|
typeof v === 'object' && v !== null && !Array.isArray(v) &&
|
|
1015
1012
|
!(v instanceof BallDouble) && !(v instanceof Set) &&
|
|
1016
1013
|
!(v instanceof Number) && !(v instanceof String) && !(v instanceof Boolean);
|
|
1014
|
+
defDartGetter('entries', function (this: any) {
|
|
1015
|
+
if (this instanceof Map) return [..._nativeMapEntries.call(this)].map(([k, v]: any) => ({ key: k, value: v }));
|
|
1016
|
+
if (!__isGenuineMap(this)) {
|
|
1017
|
+
throw new Error('type \'' + __ball_to_string(this) + '\' has no .entries getter (not a Map)');
|
|
1018
|
+
}
|
|
1019
|
+
return Object.entries(this).map(([k, v]: any) => ({ key: k, value: v }));
|
|
1020
|
+
});
|
|
1017
1021
|
defDartGetter('keys', function (this: any) {
|
|
1018
1022
|
if (this instanceof Map) return [..._nativeMapKeys.call(this)];
|
|
1019
1023
|
if (!__isGenuineMap(this)) {
|
|
@@ -1076,6 +1080,40 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
1076
1080
|
});
|
|
1077
1081
|
})();
|
|
1078
1082
|
|
|
1083
|
+
// std.map_keys/std.map_values/std.map_entries (the base-function-call form,
|
|
1084
|
+
// as opposed to the .keys/.values/.entries DART-GETTER-STYLE property
|
|
1085
|
+
// access the defDartGetter block above already guards) must ALSO fail loud
|
|
1086
|
+
// on a non-Map receiver instead of silently returning [] — same "genuine
|
|
1087
|
+
// Map" check, exposed as top-level helpers so compileStdCall's emitted code
|
|
1088
|
+
// can call them (#218).
|
|
1089
|
+
function __ball_map_keys(m: any): any {
|
|
1090
|
+
if (m instanceof Map) return [...m.keys()];
|
|
1091
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1092
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1093
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1094
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .keys getter (not a Map)');
|
|
1095
|
+
}
|
|
1096
|
+
return Object.keys(m);
|
|
1097
|
+
}
|
|
1098
|
+
function __ball_map_values(m: any): any {
|
|
1099
|
+
if (m instanceof Map) return [...m.values()];
|
|
1100
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1101
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1102
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1103
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .values getter (not a Map)');
|
|
1104
|
+
}
|
|
1105
|
+
return Object.values(m);
|
|
1106
|
+
}
|
|
1107
|
+
function __ball_map_entries(m: any): any {
|
|
1108
|
+
if (m instanceof Map) return [...m.entries()].map(([k, v]) => ({ key: k, value: v }));
|
|
1109
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1110
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1111
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1112
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .entries getter (not a Map)');
|
|
1113
|
+
}
|
|
1114
|
+
return Object.entries(m).map(([k, v]) => ({ key: k, value: v }));
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1079
1117
|
// ── Protobuf Struct/Value compatibility ─────────────────────────
|
|
1080
1118
|
//
|
|
1081
1119
|
// Dart's protobuf runtime wraps google.protobuf.Struct as a class
|
package/dist/preamble.js.map
CHANGED
|
@@ -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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA29C5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ball-lang/compiler",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.5",
|
|
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/compiler.ts
CHANGED
|
@@ -4451,7 +4451,27 @@ function __isUnknownFnError(e: any): boolean {
|
|
|
4451
4451
|
case "math_infinity": return "Infinity";
|
|
4452
4452
|
case "math_nan": return "NaN";
|
|
4453
4453
|
case "print": return `console.log(__ball_to_string(${this.expr(f.get("message")!)}))`;
|
|
4454
|
-
case "index":
|
|
4454
|
+
case "index": {
|
|
4455
|
+
const target = f.get("target")!;
|
|
4456
|
+
const idx = f.get("index")!;
|
|
4457
|
+
// Bracket-invoking a string-literal-named operator method (e.g.
|
|
4458
|
+
// `a['+'](b)` — the only way to call one, since TS has no `operator`
|
|
4459
|
+
// keyword) indexes with the RAW lexeme, but the compiled class
|
|
4460
|
+
// exposes the operator under its canonical __op_*__ name (#248) —
|
|
4461
|
+
// translate the lexeme so the access finds the real method instead
|
|
4462
|
+
// of a nonexistent literal '+' property (#252). "-" is ambiguous
|
|
4463
|
+
// (unary __op_neg__ vs binary __op_sub__ — a class can only define
|
|
4464
|
+
// ONE '-'-named method, so exactly one of the two properties ever
|
|
4465
|
+
// actually exists; ?? picks whichever it is without needing type
|
|
4466
|
+
// info to disambiguate at the call site).
|
|
4467
|
+
const lexeme = idx.literal?.stringValue;
|
|
4468
|
+
if (lexeme !== undefined && Object.prototype.hasOwnProperty.call(operatorIndexNames, lexeme)) {
|
|
4469
|
+
const targetStr = this.expr(target);
|
|
4470
|
+
if (lexeme === "-") return `(${targetStr}.__op_sub__ ?? ${targetStr}.__op_neg__)`;
|
|
4471
|
+
return `${targetStr}.${operatorIndexNames[lexeme]}`;
|
|
4472
|
+
}
|
|
4473
|
+
return `__ball_index(${this.expr(target)}, ${this.expr(idx)})`;
|
|
4474
|
+
}
|
|
4455
4475
|
case "null_coalesce": return `(${this.expr(f.get("left")!)} ?? ${this.expr(f.get("right")!)})`;
|
|
4456
4476
|
case "null_check": return this.expr(f.get("value")!);
|
|
4457
4477
|
case "is": {
|
|
@@ -4941,15 +4961,23 @@ function __isUnknownFnError(e: any): boolean {
|
|
|
4941
4961
|
}
|
|
4942
4962
|
case "map_keys": {
|
|
4943
4963
|
const map = f.get("map") ?? f.get("value");
|
|
4944
|
-
|
|
4964
|
+
// Fail loud on a non-Map receiver instead of silently returning [] —
|
|
4965
|
+
// that silent degradation is the class of bug that hid issue #55
|
|
4966
|
+
// (mirrors the .keys DART-GETTER guard already installed in
|
|
4967
|
+
// preamble.ts's defDartGetter block, and the engine/C++-compiler
|
|
4968
|
+
// guards for the same base function, #218).
|
|
4969
|
+
return map ? `__ball_map_keys(${this.expr(map)})` : "[]";
|
|
4945
4970
|
}
|
|
4946
4971
|
case "map_values": {
|
|
4947
4972
|
const map = f.get("map") ?? f.get("value");
|
|
4948
|
-
return map ? `
|
|
4973
|
+
return map ? `__ball_map_values(${this.expr(map)})` : "[]";
|
|
4949
4974
|
}
|
|
4950
4975
|
case "map_entries": {
|
|
4951
4976
|
const map = f.get("map") ?? f.get("value");
|
|
4952
|
-
|
|
4977
|
+
// Same silent-degradation class as map_keys/map_values (#218): a
|
|
4978
|
+
// bare Object.entries(...) on a non-Map silently returns garbage
|
|
4979
|
+
// instead of failing loud.
|
|
4980
|
+
return map ? `__ball_map_entries(${this.expr(map)})` : "[]";
|
|
4953
4981
|
}
|
|
4954
4982
|
case "map_length": {
|
|
4955
4983
|
const map = f.get("map") ?? f.get("value");
|
|
@@ -6493,6 +6521,36 @@ function unwrapLambda(e: Expression): Expression {
|
|
|
6493
6521
|
return e;
|
|
6494
6522
|
}
|
|
6495
6523
|
|
|
6524
|
+
/** Maps an operator lexeme to the canonical __op_*__ name a compiled class
|
|
6525
|
+
* exposes it under (mirrors ts/encoder's OPERATOR_CANONICAL_NAMES exactly
|
|
6526
|
+
* — double-trailing-underscore; NOT sanitize()'s single-underscore
|
|
6527
|
+
* operatorMap below, which is a separate, legacy short-name convention).
|
|
6528
|
+
* Used by std."index" to translate `a['+']` (the only way to bracket-
|
|
6529
|
+
* invoke a string-literal-named operator method) to the real property. */
|
|
6530
|
+
const operatorIndexNames: Record<string, string> = {
|
|
6531
|
+
"[]=": "__op_set_index__",
|
|
6532
|
+
"[]": "__op_get_index__",
|
|
6533
|
+
"==": "__op_eq__",
|
|
6534
|
+
"<": "__op_lt__",
|
|
6535
|
+
"<=": "__op_le__",
|
|
6536
|
+
">": "__op_gt__",
|
|
6537
|
+
">=": "__op_ge__",
|
|
6538
|
+
"<<": "__op_shl__",
|
|
6539
|
+
">>": "__op_shr__",
|
|
6540
|
+
">>>": "__op_ushr__",
|
|
6541
|
+
"+": "__op_add__",
|
|
6542
|
+
"*": "__op_mul__",
|
|
6543
|
+
"/": "__op_div__",
|
|
6544
|
+
"~/": "__op_idiv__",
|
|
6545
|
+
"%": "__op_mod__",
|
|
6546
|
+
"&": "__op_band__",
|
|
6547
|
+
"|": "__op_bor__",
|
|
6548
|
+
"^": "__op_bxor__",
|
|
6549
|
+
"~": "__op_bnot__",
|
|
6550
|
+
// "-" handled specially at the call site (unary vs binary ambiguity).
|
|
6551
|
+
"-": "__op_sub__",
|
|
6552
|
+
};
|
|
6553
|
+
|
|
6496
6554
|
function sanitize(name: string): string {
|
|
6497
6555
|
let out = name;
|
|
6498
6556
|
const colon = out.indexOf(":");
|
package/src/preamble.ts
CHANGED
|
@@ -994,14 +994,11 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
994
994
|
},
|
|
995
995
|
});
|
|
996
996
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
// .keys/.values on a non-Map must FAIL LOUD (throw a catchable error), not
|
|
1003
|
-
// silently return [] — the silent-degradation class of bug that hid issue
|
|
1004
|
-
// #55 (mirrors the fix already applied to the Dart/C++ compilers).
|
|
997
|
+
// .entries/.keys/.values on a non-Map must FAIL LOUD (throw a catchable
|
|
998
|
+
// error), not silently return [] — the silent-degradation class of bug
|
|
999
|
+
// that hid issue #55 (mirrors the fix already applied to the Dart/C++
|
|
1000
|
+
// compilers). .entries used to be the odd one out here, silently
|
|
1001
|
+
// returning [] instead of throwing — same bug family as #218.
|
|
1005
1002
|
//
|
|
1006
1003
|
// A getter installed on Object.prototype is invoked in "sloppy" (non-strict)
|
|
1007
1004
|
// script contexts with this auto-boxed to a Number/String/Boolean WRAPPER
|
|
@@ -1014,6 +1011,13 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
1014
1011
|
typeof v === 'object' && v !== null && !Array.isArray(v) &&
|
|
1015
1012
|
!(v instanceof BallDouble) && !(v instanceof Set) &&
|
|
1016
1013
|
!(v instanceof Number) && !(v instanceof String) && !(v instanceof Boolean);
|
|
1014
|
+
defDartGetter('entries', function (this: any) {
|
|
1015
|
+
if (this instanceof Map) return [..._nativeMapEntries.call(this)].map(([k, v]: any) => ({ key: k, value: v }));
|
|
1016
|
+
if (!__isGenuineMap(this)) {
|
|
1017
|
+
throw new Error('type \'' + __ball_to_string(this) + '\' has no .entries getter (not a Map)');
|
|
1018
|
+
}
|
|
1019
|
+
return Object.entries(this).map(([k, v]: any) => ({ key: k, value: v }));
|
|
1020
|
+
});
|
|
1017
1021
|
defDartGetter('keys', function (this: any) {
|
|
1018
1022
|
if (this instanceof Map) return [..._nativeMapKeys.call(this)];
|
|
1019
1023
|
if (!__isGenuineMap(this)) {
|
|
@@ -1076,6 +1080,40 @@ function __ball_cascade(target: any, ops: any[]): any {
|
|
|
1076
1080
|
});
|
|
1077
1081
|
})();
|
|
1078
1082
|
|
|
1083
|
+
// std.map_keys/std.map_values/std.map_entries (the base-function-call form,
|
|
1084
|
+
// as opposed to the .keys/.values/.entries DART-GETTER-STYLE property
|
|
1085
|
+
// access the defDartGetter block above already guards) must ALSO fail loud
|
|
1086
|
+
// on a non-Map receiver instead of silently returning [] — same "genuine
|
|
1087
|
+
// Map" check, exposed as top-level helpers so compileStdCall's emitted code
|
|
1088
|
+
// can call them (#218).
|
|
1089
|
+
function __ball_map_keys(m: any): any {
|
|
1090
|
+
if (m instanceof Map) return [...m.keys()];
|
|
1091
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1092
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1093
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1094
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .keys getter (not a Map)');
|
|
1095
|
+
}
|
|
1096
|
+
return Object.keys(m);
|
|
1097
|
+
}
|
|
1098
|
+
function __ball_map_values(m: any): any {
|
|
1099
|
+
if (m instanceof Map) return [...m.values()];
|
|
1100
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1101
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1102
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1103
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .values getter (not a Map)');
|
|
1104
|
+
}
|
|
1105
|
+
return Object.values(m);
|
|
1106
|
+
}
|
|
1107
|
+
function __ball_map_entries(m: any): any {
|
|
1108
|
+
if (m instanceof Map) return [...m.entries()].map(([k, v]) => ({ key: k, value: v }));
|
|
1109
|
+
if (typeof m !== 'object' || m === null || Array.isArray(m) ||
|
|
1110
|
+
m instanceof BallDouble || m instanceof Set ||
|
|
1111
|
+
m instanceof Number || m instanceof String || m instanceof Boolean) {
|
|
1112
|
+
throw new Error('type \'' + __ball_to_string(m) + '\' has no .entries getter (not a Map)');
|
|
1113
|
+
}
|
|
1114
|
+
return Object.entries(m).map(([k, v]) => ({ key: k, value: v }));
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1079
1117
|
// ── Protobuf Struct/Value compatibility ─────────────────────────
|
|
1080
1118
|
//
|
|
1081
1119
|
// Dart's protobuf runtime wraps google.protobuf.Struct as a class
|