UNPKG

fable-compiler

Version:
757 lines 21.9 kB
import { makeRangeStepFunction as makeDecimalRangeStepFunction } from "./Decimal"; import { makeRangeStepFunction as makeLongRangeStepFunction } from "./Long"; import { some, value } from "./Option"; import { compare, equals } from "./Util"; export class Enumerator { constructor(iter) { this.iter = iter; } MoveNext() { const cur = this.iter.next(); this.current = cur.value; return !cur.done; } get Current() { return this.current; } Reset() { throw new Error("JS iterators cannot be reset"); } Dispose() { return; } } export function getEnumerator(o) { return new Enumerator(o[Symbol.iterator]()); } export function toIterator(en) { return { next() { return en.MoveNext() ? { done: false, value: en.Current } : { done: true, value: null }; }, }; } // export function toIterable<T>(en: IEnumerable<T>): Iterable<T> { // return { // [Symbol.iterator]() { // return toIterator(en.GetEnumerator()); // }, // }; // } function __failIfNone(res) { if (res == null) { throw new Error("Seq did not contain any matching element"); } return value(res); } export function ofArray(xs) { return delay(() => unfold((i) => i < xs.length ? [xs[i], i + 1] : null, 0)); } export function allPairs(xs, ys) { let firstEl = true; const ysCache = []; return collect((x) => { if (firstEl) { firstEl = false; return map((y) => { ysCache.push(y); return [x, y]; }, ys); } else { return ysCache.map((y) => [x, y]); // return map(function (i) { // return [x, ysCache[i]]; // }, rangeNumber(0, 1, ysCache.length - 1)); } }, xs); } export function append(xs, ys) { return delay(() => { let firstDone = false; const i = xs[Symbol.iterator](); let iters = [i, null]; return unfold(() => { let cur; if (!firstDone) { cur = iters[0].next(); if (!cur.done) { return [cur.value, iters]; } else { firstDone = true; iters = [null, ys[Symbol.iterator]()]; } } cur = iters[1].next(); return !cur.done ? [cur.value, iters] : null; }, iters); }); } export function average(xs, averager) { let count = 0; const total = fold((acc, x) => { count++; return averager.Add(acc, x); }, averager.GetZero(), xs); return averager.DivideByInt(total, count); } export function averageBy(f, xs, averager) { let count = 0; const total = fold((acc, x) => { count++; return averager.Add(acc, f(x)); }, averager.GetZero(), xs); return averager.DivideByInt(total, count); } export function concat(xs) { return delay(() => { const iter = xs[Symbol.iterator](); let output = { value: null }; return unfold((innerIter) => { let hasFinished = false; while (!hasFinished) { if (innerIter == null) { const cur = iter.next(); if (!cur.done) { innerIter = cur.value[Symbol.iterator](); } else { hasFinished = true; } } else { const cur = innerIter.next(); if (!cur.done) { output = { value: cur.value }; hasFinished = true; } else { innerIter = null; } } } return innerIter != null && output != null ? [output.value, innerIter] : null; }, null); }); } export function collect(f, xs) { return concat(map(f, xs)); } export function choose(f, xs) { return delay(() => unfold((iter) => { let cur = iter.next(); while (!cur.done) { const y = f(cur.value); if (y != null) { return [value(y), iter]; } cur = iter.next(); } return null; }, xs[Symbol.iterator]())); } export function compareWith(f, xs, ys) { const nonZero = tryFind((i) => i !== 0, map2((x, y) => f(x, y), xs, ys)); return nonZero != null ? value(nonZero) : length(xs) - length(ys); } export function delay(f) { return { [Symbol.iterator]: () => f()[Symbol.iterator](), }; } export function empty() { return unfold(() => void 0); } export function enumerateFromFunctions(factory, moveNext, current) { return delay(() => unfold((e) => moveNext(e) ? [current(e), e] : null, factory())); } export function enumerateWhile(cond, xs) { return concat(unfold(() => cond() ? [xs, true] : null)); } export function enumerateThenFinally(xs, finalFn) { return delay(() => { let iter; try { iter = xs[Symbol.iterator](); } catch (err) { return void 0; } finally { finalFn(); } return unfold((it) => { try { const cur = it.next(); return !cur.done ? [cur.value, it] : null; } catch (err) { return void 0; } finally { finalFn(); } }, iter); }); } export function enumerateUsing(disp, work) { let isDisposed = false; const disposeOnce = () => { if (!isDisposed) { isDisposed = true; disp.Dispose(); } }; try { return enumerateThenFinally(work(disp), disposeOnce); } catch (err) { return void 0; } finally { disposeOnce(); } } export function exactlyOne(xs) { const iter = xs[Symbol.iterator](); const fst = iter.next(); if (fst.done) { throw new Error("Seq was empty"); } const snd = iter.next(); if (!snd.done) { throw new Error("Seq had multiple items"); } return fst.value; } export function except(itemsToExclude, source) { const exclusionItems = Array.from(itemsToExclude); const testIsNotInExclusionItems = (element) => !exclusionItems.some((excludedItem) => equals(excludedItem, element)); return filter(testIsNotInExclusionItems, source); } export function exists(f, xs) { let cur; for (const iter = xs[Symbol.iterator]();;) { cur = iter.next(); if (cur.done) { break; } if (f(cur.value)) { return true; } } return false; } export function exists2(f, xs, ys) { let cur1; let cur2; for (const iter1 = xs[Symbol.iterator](), iter2 = ys[Symbol.iterator]();;) { cur1 = iter1.next(); cur2 = iter2.next(); if (cur1.done || cur2.done) { break; } if (f(cur1.value, cur2.value)) { return true; } } return false; } export function forAll(f, xs) { return !exists((x) => !f(x), xs); } export function forAll2(f, xs, ys) { return !exists2((x, y) => !f(x, y), xs, ys); } export function contains(i, xs) { return exists((x) => equals(x, i), xs); } export function filter(f, xs) { return delay(() => unfold((iter) => { let cur = iter.next(); while (!cur.done) { if (f(cur.value)) { return [cur.value, iter]; } cur = iter.next(); } return null; }, xs[Symbol.iterator]())); } export function where(f, xs) { return filter(f, xs); } export function fold(f, acc, xs) { if (Array.isArray(xs) || ArrayBuffer.isView(xs)) { return xs.reduce(f, acc); } else { let cur; for (let i = 0, iter = xs[Symbol.iterator]();; i++) { cur = iter.next(); if (cur.done) { break; } acc = f(acc, cur.value, i); } return acc; } } export function foldBack(f, xs, acc) { const arr = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs : Array.from(xs); for (let i = arr.length - 1; i >= 0; i--) { acc = f(arr[i], acc, i); } return acc; } export function fold2(f, acc, xs, ys) { const iter1 = xs[Symbol.iterator](); const iter2 = ys[Symbol.iterator](); let cur1; let cur2; for (let i = 0;; i++) { cur1 = iter1.next(); cur2 = iter2.next(); if (cur1.done || cur2.done) { break; } acc = f(acc, cur1.value, cur2.value, i); } return acc; } export function foldBack2(f, xs, ys, acc) { const ar1 = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs : Array.from(xs); const ar2 = Array.isArray(ys) || ArrayBuffer.isView(ys) ? ys : Array.from(ys); for (let i = ar1.length - 1; i >= 0; i--) { acc = f(ar1[i], ar2[i], acc, i); } return acc; } export function tryHead(xs) { const iter = xs[Symbol.iterator](); const cur = iter.next(); return cur.done ? null : some(cur.value); } export function head(xs) { return __failIfNone(tryHead(xs)); } export function initialize(n, f) { return delay(() => unfold((i) => i < n ? [f(i), i + 1] : null, 0)); } export function initializeInfinite(f) { return delay(() => unfold((i) => [f(i), i + 1], 0)); } export function tryItem(i, xs) { if (i < 0) { return null; } if (Array.isArray(xs) || ArrayBuffer.isView(xs)) { return i < xs.length ? some(xs[i]) : null; } for (let j = 0, iter = xs[Symbol.iterator]();; j++) { const cur = iter.next(); if (cur.done) { break; } if (j === i) { return some(cur.value); } } return null; } export function item(i, xs) { return __failIfNone(tryItem(i, xs)); } export function iterate(f, xs) { fold((_, x) => f(x), null, xs); } export function iterate2(f, xs, ys) { fold2((_, x, y) => f(x, y), null, xs, ys); } export function iterateIndexed(f, xs) { fold((_, x, i) => f(i, x), null, xs); } export function iterateIndexed2(f, xs, ys) { fold2((_, x, y, i) => f(i, x, y), null, xs, ys); } export function isEmpty(xs) { const i = xs[Symbol.iterator](); return i.next().done; } export function tryLast(xs) { return isEmpty(xs) ? null : some(reduce((_, x) => x, xs)); } export function last(xs) { return __failIfNone(tryLast(xs)); } export function length(xs) { return Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs.length : fold((acc, x) => acc + 1, 0, xs); } export function map(f, xs) { return delay(() => unfold((iter) => { const cur = iter.next(); return !cur.done ? [f(cur.value), iter] : null; }, xs[Symbol.iterator]())); } export function mapIndexed(f, xs) { return delay(() => { let i = 0; return unfold((iter) => { const cur = iter.next(); return !cur.done ? [f(i++, cur.value), iter] : null; }, xs[Symbol.iterator]()); }); } export function indexed(xs) { return mapIndexed((i, x) => [i, x], xs); } export function map2(f, xs, ys) { return delay(() => { const iter1 = xs[Symbol.iterator](); const iter2 = ys[Symbol.iterator](); return unfold(() => { const cur1 = iter1.next(); const cur2 = iter2.next(); return !cur1.done && !cur2.done ? [f(cur1.value, cur2.value), null] : null; }); }); } export function mapIndexed2(f, xs, ys) { return delay(() => { let i = 0; const iter1 = xs[Symbol.iterator](); const iter2 = ys[Symbol.iterator](); return unfold(() => { const cur1 = iter1.next(); const cur2 = iter2.next(); return !cur1.done && !cur2.done ? [f(i++, cur1.value, cur2.value), null] : null; }); }); } export function map3(f, xs, ys, zs) { return delay(() => { const iter1 = xs[Symbol.iterator](); const iter2 = ys[Symbol.iterator](); const iter3 = zs[Symbol.iterator](); return unfold(() => { const cur1 = iter1.next(); const cur2 = iter2.next(); const cur3 = iter3.next(); return !cur1.done && !cur2.done && !cur3.done ? [f(cur1.value, cur2.value, cur3.value), null] : null; }); }); } export function mapFold(f, acc, xs, transform) { const result = []; let r; let cur; for (let i = 0, iter = xs[Symbol.iterator]();; i++) { cur = iter.next(); if (cur.done) { break; } [r, acc] = f(acc, cur.value); result.push(r); } return transform !== void 0 ? [transform(result), acc] : [result, acc]; } export function mapFoldBack(f, xs, acc, transform) { const arr = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs : Array.from(xs); const result = []; let r; for (let i = arr.length - 1; i >= 0; i--) { [r, acc] = f(arr[i], acc); result.push(r); } return transform !== void 0 ? [transform(result), acc] : [result, acc]; } export function max(xs, comparer) { const compareFn = comparer != null ? comparer.Compare : compare; return reduce((acc, x) => compareFn(acc, x) === 1 ? acc : x, xs); } export function maxBy(f, xs, comparer) { const compareFn = comparer != null ? comparer.Compare : compare; return reduce((acc, x) => compareFn(f(acc), f(x)) === 1 ? acc : x, xs); } export function min(xs, comparer) { const compareFn = comparer != null ? comparer.Compare : compare; return reduce((acc, x) => compareFn(acc, x) === -1 ? acc : x, xs); } export function minBy(f, xs, comparer) { const compareFn = comparer != null ? comparer.Compare : compare; return reduce((acc, x) => compareFn(f(acc), f(x)) === -1 ? acc : x, xs); } export function pairwise(xs) { return skip(2, scan((last, next) => [last[1], next], [0, 0], xs)); } export function rangeChar(first, last) { return delay(() => unfold((x) => x <= last ? [x, String.fromCharCode(x.charCodeAt(0) + 1)] : null, first)); } export function rangeLong(first, step, last, unsigned) { const stepFn = makeLongRangeStepFunction(step, last, unsigned); return delay(() => unfold(stepFn, first)); } export function rangeDecimal(first, step, last) { const stepFn = makeDecimalRangeStepFunction(step, last); return delay(() => unfold(stepFn, first)); } export function rangeNumber(first, step, last) { if (step === 0) { throw new Error("Step cannot be 0"); } return delay(() => unfold((x) => step > 0 && x <= last || step < 0 && x >= last ? [x, x + step] : null, first)); } export function readOnly(xs) { return map((x) => x, xs); } export function reduce(f, xs) { if (Array.isArray(xs) || ArrayBuffer.isView(xs)) { return xs.reduce(f); } const iter = xs[Symbol.iterator](); let cur = iter.next(); if (cur.done) { throw new Error("Seq was empty"); } let acc = cur.value; while (true) { cur = iter.next(); if (cur.done) { break; } acc = f(acc, cur.value); } return acc; } export function reduceBack(f, xs) { const ar = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs : Array.from(xs); if (ar.length === 0) { throw new Error("Seq was empty"); } let acc = ar[ar.length - 1]; for (let i = ar.length - 2; i >= 0; i--) { acc = f(ar[i], acc, i); } return acc; } export function replicate(n, x) { return initialize(n, () => x); } export function reverse(xs) { const ar = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs.slice(0) : Array.from(xs); return ofArray(ar.reverse()); } export function scan(f, seed, xs) { return delay(() => { const iter = xs[Symbol.iterator](); return unfold((acc) => { if (acc == null) { return [seed, seed]; } const cur = iter.next(); if (!cur.done) { acc = f(acc, cur.value); return [acc, acc]; } return void 0; }, null); }); } export function scanBack(f, xs, seed) { return reverse(scan((acc, x) => f(x, acc), seed, reverse(xs))); } export function singleton(y) { return [y]; } export function skip(n, xs) { return { [Symbol.iterator]: () => { const iter = xs[Symbol.iterator](); for (let i = 1; i <= n; i++) { if (iter.next().done) { throw new Error("Seq has not enough elements"); } } return iter; }, }; } export function skipWhile(f, xs) { return delay(() => { let hasPassed = false; return filter((x) => hasPassed || (hasPassed = !f(x)), xs); }); } export function sortWith(f, xs) { const ys = Array.from(xs); return ofArray(ys.sort(f)); } export function sum(xs, adder) { return fold((acc, x) => adder.Add(acc, x), adder.GetZero(), xs); } export function sumBy(f, xs, adder) { return fold((acc, x) => adder.Add(acc, f(x)), adder.GetZero(), xs); } export function tail(xs) { const iter = xs[Symbol.iterator](); const cur = iter.next(); if (cur.done) { throw new Error("Seq was empty"); } return { [Symbol.iterator]: () => iter, }; } export function take(n, xs, truncate = false) { return delay(() => { const iter = xs[Symbol.iterator](); return unfold((i) => { if (i < n) { const cur = iter.next(); if (!cur.done) { return [cur.value, i + 1]; } if (!truncate) { throw new Error("Seq has not enough elements"); } } return void 0; }, 0); }); } export function truncate(n, xs) { return take(n, xs, true); } export function takeWhile(f, xs) { return delay(() => { const iter = xs[Symbol.iterator](); return unfold((i) => { const cur = iter.next(); if (!cur.done && f(cur.value)) { return [cur.value, null]; } return void 0; }, 0); }); } export function tryFind(f, xs, defaultValue) { for (let i = 0, iter = xs[Symbol.iterator]();; i++) { const cur = iter.next(); if (cur.done) { break; } if (f(cur.value, i)) { return some(cur.value); } } return defaultValue === void 0 ? null : some(defaultValue); } export function find(f, xs) { return __failIfNone(tryFind(f, xs)); } export function tryFindBack(f, xs, defaultValue) { const arr = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs.slice(0) : Array.from(xs); return tryFind(f, arr.reverse(), defaultValue); } export function findBack(f, xs) { return __failIfNone(tryFindBack(f, xs)); } export function tryFindIndex(f, xs) { for (let i = 0, iter = xs[Symbol.iterator]();; i++) { const cur = iter.next(); if (cur.done) { break; } if (f(cur.value, i)) { return i; } } return null; } export function findIndex(f, xs) { return __failIfNone(tryFindIndex(f, xs)); } export function tryFindIndexBack(f, xs) { const arr = Array.isArray(xs) || ArrayBuffer.isView(xs) ? xs.slice(0) : Array.from(xs); for (let i = arr.length - 1; i >= 0; i--) { if (f(arr[i], i)) { return i; } } return null; } export function findIndexBack(f, xs) { return __failIfNone(tryFindIndexBack(f, xs)); } export function tryPick(f, xs) { for (let i = 0, iter = xs[Symbol.iterator]();; i++) { const cur = iter.next(); if (cur.done) { break; } const y = f(cur.value, i); if (y != null) { return y; } } return null; } export function pick(f, xs) { return __failIfNone(tryPick(f, xs)); } export function unfold(f, fst) { return { [Symbol.iterator]: () => { // Capture a copy of the first value in the closure // so the sequence is restarted every time, see #1230 let acc = fst; return { next: () => { const res = f(acc); if (res != null) { acc = res[1]; return { done: false, value: res[0] }; } return { done: true }; }, }; }, }; } export function zip(xs, ys) { return map2((x, y) => [x, y], xs, ys); } export function zip3(xs, ys, zs) { return map3((x, y, z) => [x, y, z], xs, ys, zs); } export function windowed(windowSize, source) { if (windowSize <= 0) { throw new Error("windowSize must be positive"); } return { [Symbol.iterator]: () => { let window = []; const iter = source[Symbol.iterator](); return { next: () => { let cur; while (window.length < windowSize) { if ((cur = iter.next()).done) { return { done: true }; } window.push(cur.value); } const value = window; window = window.slice(1); return { done: false, value }; }, }; }, }; } //# sourceMappingURL=Seq.js.map