@ball-lang/engine 1.4.3 → 1.4.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/compiled_engine.d.ts +1 -0
- package/dist/compiled_engine.d.ts.map +1 -1
- package/dist/compiled_engine.js +56 -16
- package/dist/compiled_engine.js.map +1 -1
- package/dist/engine_setup.d.ts.map +1 -1
- package/dist/engine_setup.js +35 -4
- package/dist/engine_setup.js.map +1 -1
- package/package.json +4 -2
- package/src/compiled_engine.ts +57 -16
- package/src/engine_setup.ts +34 -3
package/src/compiled_engine.ts
CHANGED
|
@@ -1389,7 +1389,7 @@ export class BallEngine {
|
|
|
1389
1389
|
this.moduleHandlers = moduleHandlers;
|
|
1390
1390
|
this._validateProgramLimits();
|
|
1391
1391
|
if (enableProfiling) {
|
|
1392
|
-
this._callCounts =
|
|
1392
|
+
this._callCounts = {};
|
|
1393
1393
|
}
|
|
1394
1394
|
for (const handler of this.moduleHandlers) {
|
|
1395
1395
|
handler.init(this);
|
|
@@ -1428,7 +1428,7 @@ export class BallEngine {
|
|
|
1428
1428
|
}
|
|
1429
1429
|
|
|
1430
1430
|
profilingReport(): any {
|
|
1431
|
-
return Map.unmodifiable((this._callCounts ??
|
|
1431
|
+
return Map.unmodifiable((this._callCounts ?? {}));
|
|
1432
1432
|
}
|
|
1433
1433
|
|
|
1434
1434
|
callFunction(module: any, function_: any, input: any): any {
|
|
@@ -2212,7 +2212,7 @@ export class BallEngine {
|
|
|
2212
2212
|
fields[entry.key] = entry.value;
|
|
2213
2213
|
}
|
|
2214
2214
|
}
|
|
2215
|
-
return new BallObject({ typeName: typeName, superObject: __ball_index(instance, '__super__'), fields: fields, methods: (__ball_index(instance, '__methods__') ??
|
|
2215
|
+
return new BallObject({ typeName: typeName, superObject: __ball_index(instance, '__super__'), fields: fields, methods: (__ball_index(instance, '__methods__') ?? {}) });
|
|
2216
2216
|
}
|
|
2217
2217
|
|
|
2218
2218
|
async _invokeSuperConstructor(childCtor: any, superclass: any, resolvedParams: any): Promise<any> {
|
|
@@ -3385,9 +3385,6 @@ export class BallEngine {
|
|
|
3385
3385
|
}
|
|
3386
3386
|
}
|
|
3387
3387
|
}
|
|
3388
|
-
if (((__ball_eq(name, 'List') || __ball_eq(name, 'Map')) || __ball_eq(name, 'Set'))) {
|
|
3389
|
-
return { ['__class_ref__']: name, ['__type__']: '__builtin_class__' };
|
|
3390
|
-
}
|
|
3391
3388
|
if (scope.has(name)) {
|
|
3392
3389
|
let bound = scope.lookup(name);
|
|
3393
3390
|
if (!__ball_eq(bound, null)) {
|
|
@@ -3499,6 +3496,9 @@ export class BallEngine {
|
|
|
3499
3496
|
this._globalScope.bind(staticField.fullName, value);
|
|
3500
3497
|
return value;
|
|
3501
3498
|
}
|
|
3499
|
+
if (((__ball_eq(name, 'List') || __ball_eq(name, 'Map')) || __ball_eq(name, 'Set'))) {
|
|
3500
|
+
return { ['__class_ref__']: name, ['__type__']: '__builtin_class__' };
|
|
3501
|
+
}
|
|
3502
3502
|
return scope.lookup(name);
|
|
3503
3503
|
}
|
|
3504
3504
|
|
|
@@ -3992,15 +3992,17 @@ export class BallEngine {
|
|
|
3992
3992
|
}
|
|
3993
3993
|
let instanceFields = {};
|
|
3994
3994
|
let allFieldNames = this._collectAllFieldNames(msg.typeName);
|
|
3995
|
-
for (const fieldName of typeDef.fieldNames) {
|
|
3996
|
-
instanceFields[fieldName] = null;
|
|
3997
|
-
}
|
|
3998
3995
|
for (const entry of fields.entries) {
|
|
3999
3996
|
if (!entry.key.startsWith('arg')) {
|
|
4000
3997
|
instanceFields[entry.key] = entry.value;
|
|
4001
3998
|
}
|
|
4002
3999
|
}
|
|
4003
4000
|
this._initFieldDefaults(msg.typeName, instanceFields);
|
|
4001
|
+
for (const fieldName of typeDef.fieldNames) {
|
|
4002
|
+
if (!(fieldName in instanceFields)) {
|
|
4003
|
+
instanceFields[fieldName] = null;
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4004
4006
|
let ctorEntry = this._lookupConstructor(msg.typeName);
|
|
4005
4007
|
let resolvedParams = {};
|
|
4006
4008
|
if ((!__ball_eq(ctorEntry, null) && hasMetadata(ctorEntry.func))) {
|
|
@@ -4282,6 +4284,24 @@ export class BallEngine {
|
|
|
4282
4284
|
if ((__ball_eq(trimmed, '""') || __ball_eq(trimmed, '\'\''))) {
|
|
4283
4285
|
return '';
|
|
4284
4286
|
}
|
|
4287
|
+
if ((((trimmed.length >= 2) && trimmed.startsWith('[')) && trimmed.endsWith(']'))) {
|
|
4288
|
+
let inner = trimmed.substring(1, __ball_sub(trimmed.length, 1)).trim();
|
|
4289
|
+
if ((inner.length === 0)) {
|
|
4290
|
+
return [];
|
|
4291
|
+
}
|
|
4292
|
+
if ((!inner.includes('[') && !inner.includes('{'))) {
|
|
4293
|
+
return [...inner.split(',').map(((s) => {
|
|
4294
|
+
const input = s;
|
|
4295
|
+
return s.trim();
|
|
4296
|
+
})).filter(((s) => {
|
|
4297
|
+
const input = s;
|
|
4298
|
+
return !(s.length === 0);
|
|
4299
|
+
})).map(((s) => {
|
|
4300
|
+
const input = s;
|
|
4301
|
+
return this._parseInitializer(s);
|
|
4302
|
+
}))];
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4285
4305
|
let intVal = int.tryParse(trimmed);
|
|
4286
4306
|
if (!__ball_eq(intVal, null)) {
|
|
4287
4307
|
return intVal;
|
|
@@ -4290,7 +4310,7 @@ export class BallEngine {
|
|
|
4290
4310
|
if (!__ball_eq(doubleVal, null)) {
|
|
4291
4311
|
return doubleVal;
|
|
4292
4312
|
}
|
|
4293
|
-
if (((trimmed.startsWith('\'') && trimmed.endsWith('\'')) || (trimmed.startsWith('"') && trimmed.endsWith('"')))) {
|
|
4313
|
+
if (((trimmed.length >= 2) && ((trimmed.startsWith('\'') && trimmed.endsWith('\'')) || (trimmed.startsWith('"') && trimmed.endsWith('"'))))) {
|
|
4294
4314
|
return trimmed.substring(1, __ball_sub(trimmed.length, 1));
|
|
4295
4315
|
}
|
|
4296
4316
|
return trimmed;
|
|
@@ -4334,6 +4354,12 @@ export class BallEngine {
|
|
|
4334
4354
|
superFields[fname] = __ball_index(childFields, fname);
|
|
4335
4355
|
}
|
|
4336
4356
|
}
|
|
4357
|
+
this._initFieldDefaults(superclass, superFields);
|
|
4358
|
+
for (const fname of parentTypeDef.fieldNames) {
|
|
4359
|
+
if (!(fname in superFields)) {
|
|
4360
|
+
superFields[fname] = null;
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4337
4363
|
let parentMethods = this._resolveTypeMethods(qualifiedSuperclass);
|
|
4338
4364
|
let parentMethodsMap = parentMethods.cast();
|
|
4339
4365
|
let grandparent = parentTypeDef.superclass;
|
|
@@ -4527,7 +4553,7 @@ export class BallEngine {
|
|
|
4527
4553
|
_lazyFields(call: any): any {
|
|
4528
4554
|
const input = call;
|
|
4529
4555
|
if ((!hasInput(call) || !__ball_eq(whichExpr(call.input), Expression_Expr.messageCreation))) {
|
|
4530
|
-
return
|
|
4556
|
+
return {};
|
|
4531
4557
|
}
|
|
4532
4558
|
let result = {};
|
|
4533
4559
|
for (const f of call.input.messageCreation.fields) {
|
|
@@ -5796,6 +5822,20 @@ export class BallEngine {
|
|
|
5796
5822
|
throw new _FlowSignal('goto', { label: label });
|
|
5797
5823
|
}
|
|
5798
5824
|
|
|
5825
|
+
_gotoSignalLabel(signal: any): any {
|
|
5826
|
+
const input = signal;
|
|
5827
|
+
if ((signal instanceof _FlowSignal)) {
|
|
5828
|
+
return (__ball_eq(signal.kind, 'goto') ? signal.label : null);
|
|
5829
|
+
}
|
|
5830
|
+
if ((typeof signal === 'string')) {
|
|
5831
|
+
return signal;
|
|
5832
|
+
}
|
|
5833
|
+
if (((typeof signal === 'object' && signal !== null && !Array.isArray(signal) && !(signal instanceof BallDouble) && !(signal instanceof Set)) && __ball_eq(__ball_index(signal, 'kind'), 'goto'))) {
|
|
5834
|
+
let l = __ball_index(signal, 'label');
|
|
5835
|
+
return ((typeof l === 'string') ? l : null);
|
|
5836
|
+
}
|
|
5837
|
+
}
|
|
5838
|
+
|
|
5799
5839
|
async _evalLabel(call: any, scope: any): Promise<any> {
|
|
5800
5840
|
let fields = this._lazyFields(call);
|
|
5801
5841
|
let label = this._stringFieldVal(fields, 'name');
|
|
@@ -5812,13 +5852,13 @@ export class BallEngine {
|
|
|
5812
5852
|
} catch (__ball_active_error) {
|
|
5813
5853
|
const e = __ball_active_error;
|
|
5814
5854
|
let signal = e;
|
|
5815
|
-
if (
|
|
5855
|
+
if (__ball_eq(this._gotoSignalLabel(signal), label)) {
|
|
5816
5856
|
repeat = true;
|
|
5817
5857
|
} else {
|
|
5818
5858
|
throw __ball_active_error;
|
|
5819
5859
|
}
|
|
5820
5860
|
}
|
|
5821
|
-
if ((
|
|
5861
|
+
if ((!repeat && __ball_eq(this._gotoSignalLabel(result), label))) {
|
|
5822
5862
|
repeat = true;
|
|
5823
5863
|
}
|
|
5824
5864
|
}
|
|
@@ -8294,7 +8334,8 @@ export class BallEngine {
|
|
|
8294
8334
|
}
|
|
8295
8335
|
if (__ball_eq(typeName, null)) {
|
|
8296
8336
|
let parts = [];
|
|
8297
|
-
|
|
8337
|
+
let rawMap = (((typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof BallDouble) && !(v instanceof Set)) && !(false /* BallMap is Map in TS */)) ? v : map);
|
|
8338
|
+
for (const e of rawMap.entries) {
|
|
8298
8339
|
let k = await this._ballToStringAsync(e.key);
|
|
8299
8340
|
let val = await this._ballToStringAsync(e.value);
|
|
8300
8341
|
parts = (parts.push(((__ball_to_string(k) + ': ') + __ball_to_string(val))), parts);
|
|
@@ -9018,7 +9059,7 @@ export class BallEngine {
|
|
|
9018
9059
|
}
|
|
9019
9060
|
let list = this._stdAsList(fields);
|
|
9020
9061
|
if (__ball_eq(list, null)) {
|
|
9021
|
-
return
|
|
9062
|
+
return {};
|
|
9022
9063
|
}
|
|
9023
9064
|
let result = {};
|
|
9024
9065
|
let positional = 1;
|
|
@@ -9979,7 +10020,7 @@ function _ballToDouble(value: any): any {
|
|
|
9979
10020
|
|
|
9980
10021
|
function _ballValueIsSet(v: any): any {
|
|
9981
10022
|
const input = v;
|
|
9982
|
-
return ((
|
|
10023
|
+
return ((typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof BallDouble) && !(v instanceof Set)) && (_kBallSetTag in v));
|
|
9983
10024
|
}
|
|
9984
10025
|
|
|
9985
10026
|
function _ballIsInt(v: any): any {
|
package/src/engine_setup.ts
CHANGED
|
@@ -485,8 +485,16 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
485
485
|
if (v && typeof v === 'object' && v.__ball_generator__ === true) return __bts(v.values);
|
|
486
486
|
if (Array.isArray(v)) return '[' + v.map(__bts).join(', ') + ']';
|
|
487
487
|
if (v instanceof Map) {
|
|
488
|
+
// NOT `v.entries()` — the compiled engine's own preamble shadows
|
|
489
|
+
// `Map.prototype.entries` with a Dart-style GETTER (returning an array
|
|
490
|
+
// of {key,value} objects, matching Dart's `Map.entries` property) so
|
|
491
|
+
// Ball's `.entries` field access works. That shadow makes `v.entries`
|
|
492
|
+
// non-callable, so `v.entries()` throws "not a function" for any real
|
|
493
|
+
// Map value. Iterate the Map directly instead — a Map's default
|
|
494
|
+
// iterator already yields [key, value] pairs and is unaffected by the
|
|
495
|
+
// entries/keys/values property shadowing.
|
|
488
496
|
const parts: string[] = [];
|
|
489
|
-
for (const [k, val] of v
|
|
497
|
+
for (const [k, val] of v) parts.push(__bts(k) + ': ' + __bts(val));
|
|
490
498
|
return '{' + parts.join(', ') + '}';
|
|
491
499
|
}
|
|
492
500
|
if (v instanceof Set) return '{' + [...v].map(__bts).join(', ') + '}';
|
|
@@ -906,7 +914,16 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
906
914
|
_r('string_char_at', (i: any) => { const m = _m(i); return String(m['value'] ?? m['string'] ?? '').charAt(Number(m['index'] ?? m['arg0'] ?? 0)); });
|
|
907
915
|
_r('string_to_int', (i: any) => {
|
|
908
916
|
const m = _m(i); const s = String(m['value'] ?? m['string'] ?? i ?? '').trim();
|
|
909
|
-
|
|
917
|
+
// `.message` must be the bare invalid text (Dart's `FormatException.message`
|
|
918
|
+
// is never prefixed with the type name — only `.toString()` adds that).
|
|
919
|
+
// Setting `name: 'FormatException'` (not just a `message` override) lets
|
|
920
|
+
// the default `Error.prototype.toString()` ("name: message") produce the
|
|
921
|
+
// Dart-correct "FormatException: <text>" for anything that prints the
|
|
922
|
+
// caught exception itself rather than `.message`. Previously the message
|
|
923
|
+
// override clobbered the "FormatException: " prefix right back out,
|
|
924
|
+
// leaving `.name` as the native "Error" — undetected because no
|
|
925
|
+
// conformance fixture prints a caught FormatException directly.
|
|
926
|
+
if (!/^-?\d+$/.test(s)) throw Object.assign(new Error(s), { name: 'FormatException', __type__: 'FormatException' });
|
|
910
927
|
return parseInt(s, 10);
|
|
911
928
|
});
|
|
912
929
|
_r('writeCharCode', (i: any) => { const m = _m(i); const self = m['self']; if (typeof self === 'object' && self !== null) { self['__buffer__'] = (self['__buffer__'] ?? '') + String.fromCharCode(Number(m['arg0'] ?? m['value'] ?? 0)); } return null; });
|
|
@@ -965,7 +982,21 @@ export function createEngineSetup(mod: EngineModule) {
|
|
|
965
982
|
return true;
|
|
966
983
|
});
|
|
967
984
|
_r('concat', (i: any) => { const m = _m(i); return String(m['left'] ?? '') + String(m['right'] ?? ''); });
|
|
968
|
-
|
|
985
|
+
// `?? i` (used by most unary helpers below) can't distinguish "no `value`
|
|
986
|
+
// field" from "`value` is explicitly null" — for every OTHER helper that's
|
|
987
|
+
// harmless (a null numeric/string arg just coerces away), but for
|
|
988
|
+
// null_check it inverts the function's entire purpose: `x!` where `x` is
|
|
989
|
+
// null must throw (matches the Dart engine's `_extractUnaryArg` + null
|
|
990
|
+
// check — see engine_std.dart's 'null_check' and its
|
|
991
|
+
// "throws BallRuntimeError on null" test), yet `m['value'] ?? i` silently
|
|
992
|
+
// fell back to the (truthy) input map and returned it instead of
|
|
993
|
+
// throwing. hasOwnProperty-gate so an explicit null is honored.
|
|
994
|
+
_r('null_check', (i: any) => {
|
|
995
|
+
const m = _m(i);
|
|
996
|
+
const v = Object.prototype.hasOwnProperty.call(m, 'value') ? m['value'] : i;
|
|
997
|
+
if (v == null) throw new Error('Null check operator used on a null value');
|
|
998
|
+
return v;
|
|
999
|
+
});
|
|
969
1000
|
_r('compare_to', (i: any) => {
|
|
970
1001
|
const m = _m(i); const l = m['left'] ?? m['value'] ?? m['self'] ?? m['a'] ?? 0; const r = m['right'] ?? m['other'] ?? m['arg0'] ?? m['b'] ?? 0;
|
|
971
1002
|
if (typeof l === 'string' && typeof r === 'string') return l < r ? -1 : l > r ? 1 : 0;
|