@jplorg/jpl
Version:
JPL interpreter
99 lines (98 loc) • 4.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _library = require("../../../library");
var _utils = require("../utils");
function shallowCompareArrays(a, b) {
if (a.length !== b.length) return false;
return a.every((v, i) => v === b[i]);
}
var _default = exports.default = {
/** { from: [op], to: [op], optional: boolean } */
async op(runtime, input, target, params, scope, next) {
const [froms, tos] = await Promise.all([runtime.executeInstructions(params.from ?? [], [input], scope), runtime.executeInstructions(params.to ?? [], [input], scope)]);
const ranges = runtime.muxOne([runtime.unwrapValues(froms), runtime.unwrapValues(tos)], (from, to) => [from, to]);
const iter = async (from, source) => {
// Call stack decoupling - This is necessary as some browsers (i.e. Safari) have very limited call stack sizes which result in stack overflow exceptions in certain situations.
await undefined;
scope.signal.checkHealth();
if (from >= ranges.length) return [source];
const v = runtime.unwrapValue(source);
const tv = runtime.type(source);
const [start, end] = ranges[from];
const ts = runtime.type(start);
const te = runtime.type(end);
switch (tv) {
case 'array':
if (['number', 'null'].includes(ts) && ['number', 'null'].includes(te)) {
return runtime.muxAll([await next(v.slice(Math.trunc(start ?? 0), Math.trunc(end ?? v.length)))], async output => {
if (output === undefined) return iter(from + 1, source);
return iter(from + 1, await runtime.alterValue(source, value => {
const result = runtime.unwrapValue(output);
const tr = runtime.type(result);
switch (tr) {
case 'null':
case 'array':
{
let s = Math.trunc(start ?? 0);
let e = Math.trunc(end ?? value.length);
s = s >= 0 ? Math.min(value.length, s) : Math.max(0, value.length + s);
e = Math.max(s, e >= 0 ? Math.min(value.length, e) : Math.max(0, value.length + e));
if (shallowCompareArrays(value.slice(s, e), result ?? [])) return value;
const c = [...value];
c.splice(s, e - s, ...(result ?? []));
return c;
}
default:
}
throw new _library.JPLTypeError('cannot assign %s (%*<100v) to slice of %s (%*<100v)', tr, result, tv, value);
}));
});
}
break;
case 'string':
if (['number', 'null'].includes(ts) && ['number', 'null'].includes(te)) {
const chars = [...v];
return runtime.muxAll([await next(chars.slice(Math.trunc(start ?? 0), Math.trunc(end ?? chars.length)).join(''))], async output => {
if (output === undefined) return iter(from + 1, source);
return iter(from + 1, await runtime.alterValue(source, value => {
const result = runtime.unwrapValue(output);
const tr = runtime.type(result);
switch (tr) {
case 'null':
case 'string':
{
const chars = [...value];
let s = Math.trunc(start ?? 0);
let e = Math.trunc(end ?? chars.length);
s = s >= 0 ? Math.min(chars.length, s) : Math.max(0, chars.length + s);
e = Math.max(s, e >= 0 ? Math.min(chars.length, e) : Math.max(0, chars.length + e));
if (shallowCompareArrays(chars.slice(s, e), result ?? [])) return value;
chars.splice(s, e - s, ...(result ?? []));
return chars.join('');
}
default:
}
throw new _library.JPLTypeError('cannot assign %s (%*<100v) to slice of %s (%*<100v)', tr, result, tv, value);
}));
});
}
break;
default:
}
if (params.optional) return iter(from + 1, source);
throw new _library.JPLTypeError('cannot slice %s (%*<100v) with %s (%*<100v) and %s (%*<100v) (assignment)', tv, v, ts, start, te, end);
};
return runtime.muxOne([await iter(0, target)], output => runtime.type(output) === 'null' ? undefined : output);
},
/** { from: function, to: function, optional: boolean } */
map(runtime, params) {
return {
from: (0, _utils.call)(params.from),
to: (0, _utils.call)(params.to),
optional: runtime.assertType(params.optional, 'boolean')
};
}
};