Comparing version 31.0.0 to 31.1.0
@@ -6,2 +6,26 @@ # Change Log | ||
# [31.1.0](https://github.com/tusharmath/qio/compare/v31.0.1...v31.1.0) (2020-03-29) | ||
### Bug Fixes | ||
* update dependencies ([06fbfd2](https://github.com/tusharmath/qio/commit/06fbfd2ef833e56f802c4222a9d16f8782a91c10)) | ||
* **queue:** fix offer implementation ([5c474f6](https://github.com/tusharmath/qio/commit/5c474f63c61e75fdaac726bbd7b2dabca16b5080)) | ||
### Features | ||
* **await:** add \`setTo\` helper function ([f787b18](https://github.com/tusharmath/qio/commit/f787b18f03676ea33f67acfb5f229f2bb3e31ece)) | ||
* **chunk:** add chunking capabilities. ([2941622](https://github.com/tusharmath/qio/commit/29416224b767d0fb279a88834b31934609d83053)) | ||
* **core:** add \`Flag\` type ([d71a0be](https://github.com/tusharmath/qio/commit/d71a0bee77eca84e722d7d3e21353d0feb89c466)) | ||
### Performance Improvements | ||
* **qio:** make \`map\` and \`chain\` eager only if it's being applied on a \`constant\` value. ([1ca41c6](https://github.com/tusharmath/qio/commit/1ca41c6039e63a9ed63cab0c425c43b86e2cb5a2)) | ||
# [31.0.0](https://github.com/tusharmath/qio/compare/v30.0.1...v31.0.0) (2020-01-28) | ||
@@ -8,0 +32,0 @@ |
export { Await } from './lib/main/Await'; | ||
export { Chunk } from './lib/main/Chunk'; | ||
export { Counter } from './lib/main/Counter'; | ||
export { defaultRuntime } from './lib/runtimes/DefaultRuntime'; | ||
@@ -6,2 +8,3 @@ export { Exit } from './lib/main/Exit'; | ||
export { FiberConfig } from './lib/internals/FiberConfig'; | ||
export { Flag } from './lib/main/Flag'; | ||
export { FMap } from './lib/main/FMap'; | ||
@@ -14,3 +17,2 @@ export { IRuntime } from './lib/runtimes/IRuntime'; | ||
export { Snapshot } from './lib/main/Snapshot'; | ||
export { Counter } from './lib/main/Counter'; | ||
export { testRuntime, TestRuntime } from './lib/runtimes/TestRuntime'; |
@@ -5,2 +5,6 @@ "use strict"; | ||
exports.Await = Await_1.Await; | ||
var Chunk_1 = require("./lib/main/Chunk"); | ||
exports.Chunk = Chunk_1.Chunk; | ||
var Counter_1 = require("./lib/main/Counter"); | ||
exports.Counter = Counter_1.Counter; | ||
var DefaultRuntime_1 = require("./lib/runtimes/DefaultRuntime"); | ||
@@ -14,2 +18,4 @@ exports.defaultRuntime = DefaultRuntime_1.defaultRuntime; | ||
exports.FiberConfig = FiberConfig_1.FiberConfig; | ||
var Flag_1 = require("./lib/main/Flag"); | ||
exports.Flag = Flag_1.Flag; | ||
var FMap_1 = require("./lib/main/FMap"); | ||
@@ -27,6 +33,4 @@ exports.FMap = FMap_1.FMap; | ||
exports.Snapshot = Snapshot_1.Snapshot; | ||
var Counter_1 = require("./lib/main/Counter"); | ||
exports.Counter = Counter_1.Counter; | ||
var TestRuntime_1 = require("./lib/runtimes/TestRuntime"); | ||
exports.testRuntime = TestRuntime_1.testRuntime; | ||
exports.TestRuntime = TestRuntime_1.TestRuntime; |
@@ -7,6 +7,6 @@ import { LinkedListNode } from 'standard-data-structures'; | ||
private readonly Q; | ||
get isCancelled(): boolean; | ||
cancel(): void; | ||
get isCancelled(): boolean; | ||
push(cancellable: ICancellable): CancelId; | ||
remove(id: CancelId): void; | ||
} |
@@ -9,2 +9,5 @@ "use strict"; | ||
} | ||
get isCancelled() { | ||
return this.cancelled; | ||
} | ||
cancel() { | ||
@@ -19,5 +22,2 @@ this.cancelled = true; | ||
} | ||
get isCancelled() { | ||
return this.cancelled; | ||
} | ||
push(cancellable) { | ||
@@ -24,0 +24,0 @@ return this.Q.add(cancellable); |
@@ -7,3 +7,2 @@ import { ICancellable } from 'ts-scheduler'; | ||
export declare abstract class Fiber<A, E> { | ||
get join(): QIO<A, E>; | ||
static unsafeExecuteWith<A, E>(io: QIO<A, E>, runtime: FiberRuntime, cb?: CBExit<A, E>): ICancellable; | ||
@@ -14,7 +13,6 @@ abstract abort: QIO<void>; | ||
abstract runtime: FiberRuntime; | ||
get join(): QIO<A, E>; | ||
} | ||
export declare class FiberContext<A, E> extends Fiber<A, E> implements ICancellable { | ||
readonly runtime: FiberRuntime; | ||
get abort(): QIO<void>; | ||
get await(): QIO<Exit<A, E>>; | ||
static unsafeExecuteWith<A, E>(io: QIO<A, E>, runtime: FiberRuntime, cb?: CBExit<A, E>): FiberContext<A, E>; | ||
@@ -31,2 +29,4 @@ private static dispatchResult; | ||
private constructor(); | ||
get abort(): QIO<void>; | ||
get await(): QIO<Exit<A, E>>; | ||
cancel(): void; | ||
@@ -33,0 +33,0 @@ unsafeObserve(cb: CBExit<A, E>): ICancellable; |
@@ -28,8 +28,8 @@ "use strict"; | ||
} | ||
static unsafeExecuteWith(io, runtime, cb) { | ||
return FiberContext.unsafeExecuteWith(io, runtime, cb); | ||
} | ||
get join() { | ||
return this.await.chain(QIO_1.QIO.fromExit); | ||
} | ||
static unsafeExecuteWith(io, runtime, cb) { | ||
return FiberContext.unsafeExecuteWith(io, runtime, cb); | ||
} | ||
} | ||
@@ -51,12 +51,2 @@ exports.Fiber = Fiber; | ||
} | ||
get abort() { | ||
return QIO_1.QIO.lift(() => this.cancel()); | ||
} | ||
get await() { | ||
D(this.id, 'this.await()'); | ||
return QIO_1.QIO.uninterruptible(cb => { | ||
this.unsafeObserve(cb); | ||
return this; | ||
}); | ||
} | ||
static unsafeExecuteWith(io, runtime, cb) { | ||
@@ -72,2 +62,12 @@ const context = new FiberContext(io.asInstruction, runtime); | ||
} | ||
get abort() { | ||
return QIO_1.QIO.lift(() => this.cancel()); | ||
} | ||
get await() { | ||
D(this.id, 'this.await()'); | ||
return QIO_1.QIO.uninterruptible((cb) => { | ||
this.unsafeObserve(cb); | ||
return this; | ||
}); | ||
} | ||
cancel() { | ||
@@ -79,3 +79,3 @@ D(this.id, 'this.cancel()'); | ||
this.cancellationList.cancel(); | ||
this.observers.map(_ => _(Exit_1.Exit.cancel())); | ||
this.observers.map((_) => _(Exit_1.Exit.cancel())); | ||
} | ||
@@ -100,3 +100,3 @@ unsafeObserve(cb) { | ||
D(this.id, 'this.observers.length == ', this.observers.length); | ||
} | ||
}, | ||
}; | ||
@@ -108,3 +108,3 @@ } | ||
this.result = result; | ||
this.observers.map(_ => _(result)); | ||
this.observers.map((_) => _(result)); | ||
} | ||
@@ -183,3 +183,3 @@ init(data) { | ||
case Instructions_1.Tag.Provide: | ||
this.stackA.push(QIO_1.QIO.resume(i => { | ||
this.stackA.push(QIO_1.QIO.resume((i) => { | ||
this.stackEnv.pop(); | ||
@@ -196,7 +196,7 @@ return i; | ||
case Instructions_1.Tag.Async: | ||
const id = this.cancellationList.push(j.i0(val => { | ||
const id = this.cancellationList.push(j.i0((val) => { | ||
this.cancellationList.remove(id); | ||
this.stackA.push(QIO_1.QIO.resolve(val).asInstruction); | ||
this.unsafeEvaluate(); | ||
}, err => { | ||
}, (err) => { | ||
this.cancellationList.remove(id); | ||
@@ -203,0 +203,0 @@ this.stackA.push(QIO_1.QIO.reject(err).asInstruction); |
@@ -17,3 +17,3 @@ "use strict"; | ||
return { tag: YieldStrategyTag.INS_COUNT, maxInstructionCount }; | ||
} | ||
}, | ||
}; |
import { LinkedListNode, Option } from 'standard-data-structures'; | ||
import { QIO } from '../main/QIO'; | ||
export declare class PureMutableList<A> { | ||
static of<A = never>(): QIO<PureMutableList<A>>; | ||
private readonly list; | ||
private constructor(); | ||
get asArray(): QIO<A[]>; | ||
@@ -8,5 +11,2 @@ get isEmpty(): QIO<boolean>; | ||
get shift(): QIO<Option<A>>; | ||
static of<A = never>(): QIO<PureMutableList<A>>; | ||
private readonly list; | ||
private constructor(); | ||
add(element: A): QIO<LinkedListNode<A>>; | ||
@@ -13,0 +13,0 @@ forEach<E1>(f: (a: A) => QIO<void, E1>): QIO<void, E1>; |
@@ -9,2 +9,5 @@ "use strict"; | ||
} | ||
static of() { | ||
return QIO_1.QIO.lift(() => new PureMutableList()); | ||
} | ||
get asArray() { | ||
@@ -22,5 +25,2 @@ return QIO_1.QIO.lift(() => this.list.asArray); | ||
} | ||
static of() { | ||
return QIO_1.QIO.lift(() => new PureMutableList()); | ||
} | ||
add(element) { | ||
@@ -30,5 +30,3 @@ return QIO_1.QIO.lift(() => this.list.add(element)); | ||
forEach(f) { | ||
const itar = () => this.shift.chain(_ => _.map(f) | ||
.getOrElse(QIO_1.QIO.void()) | ||
.chain(itar)); | ||
const itar = () => this.shift.chain((_) => _.map(f).getOrElse(QIO_1.QIO.void()).chain(itar)); | ||
return itar(); | ||
@@ -35,0 +33,0 @@ } |
import { QIO } from './QIO'; | ||
export declare class Await<A, E> { | ||
get get(): QIO<A, E>; | ||
get isSet(): QIO<boolean>; | ||
private get wait(); | ||
static of<A = never, E = never>(): QIO<Await<A, E>>; | ||
@@ -11,3 +8,7 @@ readonly id: number; | ||
private result; | ||
get get(): QIO<A, E>; | ||
get isSet(): QIO<boolean>; | ||
private get wait(); | ||
set(io: QIO<A, E>): QIO<boolean>; | ||
setTo(a: A): QIO<boolean>; | ||
} |
@@ -22,5 +22,12 @@ "use strict"; | ||
} | ||
static of() { | ||
return QIO_1.QIO.lift(() => { | ||
const awt = new Await(); | ||
D(awt.id, 'this.constructor()'); | ||
return awt; | ||
}); | ||
} | ||
get get() { | ||
return QIO_1.QIO.tryM(() => this.result | ||
.map(S => S.reduce(QIO_1.QIO.reject, XX => QIO_1.QIO.resolve(XX))) | ||
.map((S) => S.reduce(QIO_1.QIO.reject, (XX) => QIO_1.QIO.resolve(XX))) | ||
.getOrElse(this.wait)); | ||
@@ -41,13 +48,6 @@ } | ||
D(this.id, 'this.Q.length', this.Q.length); | ||
} | ||
}, | ||
}; | ||
}); | ||
} | ||
static of() { | ||
return QIO_1.QIO.lift(() => { | ||
const awt = new Await(); | ||
D(awt.id, 'this.constructor()'); | ||
return awt; | ||
}); | ||
} | ||
set(io) { | ||
@@ -61,3 +61,3 @@ return QIO_1.QIO.tryM(() => { | ||
D(this.id, 'set', 'status', AwaitStatus[this.flag]); | ||
return io.asEither.encase(either => { | ||
return io.asEither.encase((either) => { | ||
this.flag = AwaitStatus.COMPLETED; | ||
@@ -76,3 +76,6 @@ D(this.id, 'set', 'status', AwaitStatus[this.flag]); | ||
} | ||
setTo(a) { | ||
return this.set(QIO_1.QIO.resolve(a)); | ||
} | ||
} | ||
exports.Await = Await; |
@@ -1,6 +0,10 @@ | ||
export declare abstract class Chunk<A> { | ||
export declare abstract class Chunk<A> implements Iterable<A> { | ||
static createN<A>(arr: A[], n: number): Chunk<A>; | ||
static empty<A>(): Chunk<A>; | ||
static from<A>(arr: A[]): Chunk<A>; | ||
static isEmpty<A>(C: Chunk<A>): C is Empty; | ||
static of<A>(A: A): Chunk<A>; | ||
abstract asArray: A[]; | ||
abstract readonly length: number; | ||
abstract [Symbol.iterator](): Iterator<A>; | ||
chain<B>(fn: (A: A) => Chunk<B>): Chunk<B>; | ||
@@ -12,1 +16,10 @@ concat(that: Chunk<A>): Chunk<A>; | ||
} | ||
declare class Empty extends Chunk<never> { | ||
readonly length = 0; | ||
get asArray(): never[]; | ||
[Symbol.iterator](): Iterator<never>; | ||
filter(fn: (A: never) => boolean): Chunk<never>; | ||
fold<S>(S: S, fn: (A: never, S: S) => S): S; | ||
map<B>(fn: (A: never) => B): Chunk<B>; | ||
} | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const split = (min, max, count, expected) => { | ||
for (let i = 0; i < count; i++) { | ||
if (i * min + (count - i) * max === expected) { | ||
return i; | ||
} | ||
} | ||
return count; | ||
}; | ||
const createChunkCapacity = (count, minSize, maxSize, distribution) => { | ||
const chunks = new Array(); | ||
for (let i = 0; i < count; i++) { | ||
chunks.push(i < distribution ? minSize : maxSize); | ||
} | ||
return chunks; | ||
}; | ||
const createChunks = (arr, chunkCount) => { | ||
const itemCount = arr.length; | ||
const chunks = new Array([]); | ||
const minChunkSize = Math.floor(arr.length / chunkCount); | ||
const maxChunkSize = minChunkSize + 1; | ||
const distribution = split(minChunkSize, maxChunkSize, chunkCount, itemCount); | ||
const chunkCapacity = createChunkCapacity(chunkCount, minChunkSize, maxChunkSize, distribution); | ||
let selectedChunk = 0; | ||
for (let i = 0; i < itemCount; i++) { | ||
if (chunks[selectedChunk].length === chunkCapacity[selectedChunk]) { | ||
selectedChunk++; | ||
chunks.push([]); | ||
} | ||
chunks[selectedChunk].push(arr[i]); | ||
} | ||
return chunks; | ||
}; | ||
class Chunk { | ||
static createN(arr, n) { | ||
return createChunks(arr, n) | ||
.map((_) => Chunk.from(_)) | ||
.reduce((a, c) => a.concat(c), Chunk.empty()); | ||
} | ||
static empty() { | ||
@@ -10,2 +47,5 @@ return new Empty(); | ||
} | ||
static isEmpty(C) { | ||
return C instanceof Empty; | ||
} | ||
static of(A) { | ||
@@ -18,2 +58,8 @@ return new Value(A); | ||
concat(that) { | ||
if (Chunk.isEmpty(that)) { | ||
return this; | ||
} | ||
if (Chunk.isEmpty(this)) { | ||
return that; | ||
} | ||
return new Concat(this, that); | ||
@@ -30,2 +76,13 @@ } | ||
} | ||
get asArray() { | ||
return this.L.asArray.concat(this.R.asArray); | ||
} | ||
*[Symbol.iterator]() { | ||
for (const i of this.L) { | ||
yield i; | ||
} | ||
for (const i of this.R) { | ||
yield i; | ||
} | ||
} | ||
filter(fn) { | ||
@@ -47,2 +104,8 @@ return new Concat(this.L.filter(fn), this.R.filter(fn)); | ||
} | ||
get asArray() { | ||
return this.array; | ||
} | ||
[Symbol.iterator]() { | ||
return this.array[Symbol.iterator](); | ||
} | ||
filter(fn) { | ||
@@ -67,2 +130,6 @@ return new ArrayC(this.array.filter(fn)); | ||
} | ||
get asArray() { | ||
return []; | ||
} | ||
*[Symbol.iterator]() { } | ||
filter(fn) { | ||
@@ -84,2 +151,8 @@ return this; | ||
} | ||
get asArray() { | ||
return [this.value]; | ||
} | ||
*[Symbol.iterator]() { | ||
yield this.value; | ||
} | ||
filter(fn) { | ||
@@ -86,0 +159,0 @@ return fn(this.value) ? new Value(this.value) : new Empty(); |
import { QIO } from '../..'; | ||
export declare class Counter { | ||
count: number; | ||
get increased(): boolean; | ||
inc: (s?: number) => QIO<number, never, unknown>; | ||
get increased(): boolean; | ||
} |
@@ -40,3 +40,3 @@ "use strict"; | ||
}, | ||
succeed: (value) => new FiberSuccess(value) | ||
succeed: (value) => new FiberSuccess(value), | ||
}; |
@@ -15,3 +15,3 @@ "use strict"; | ||
get(key) { | ||
return QIO_1.QIO.lift(() => this.cache.get(key)).chain(_ => _ === undefined ? QIO_1.QIO.reject(new NoSuchElement()) : QIO_1.QIO.resolve(_)); | ||
return QIO_1.QIO.lift(() => this.cache.get(key)).chain((_) => _ === undefined ? QIO_1.QIO.reject(new NoSuchElement()) : QIO_1.QIO.resolve(_)); | ||
} | ||
@@ -22,3 +22,3 @@ has(key) { | ||
memoize(fn) { | ||
return (a) => this.get(a).catch(() => fn(a).chain(r => this.set(a, r))); | ||
return (a) => this.get(a).catch(() => fn(a).chain((r) => this.set(a, r))); | ||
} | ||
@@ -25,0 +25,0 @@ set(key, value) { |
@@ -8,3 +8,3 @@ /// <reference types="node" /> | ||
}, Error, unknown>; | ||
export declare const readFile: (path: string | Buffer | promises.FileHandle | import("url").URL, options?: string | { | ||
export declare const readFile: (path: string | Buffer | import("url").URL | promises.FileHandle, options?: string | { | ||
encoding?: string | null | undefined; | ||
@@ -17,3 +17,3 @@ flag?: string | number | undefined; | ||
}, Error, unknown>; | ||
export declare const writeFile: (path: string | Buffer | promises.FileHandle | import("url").URL, data: any, options?: string | { | ||
export declare const writeFile: (path: string | Buffer | import("url").URL | promises.FileHandle, data: any, options?: string | { | ||
encoding?: string | null | undefined; | ||
@@ -20,0 +20,0 @@ mode?: string | number | undefined; |
@@ -5,3 +5,3 @@ import { QIO } from './QIO'; | ||
private readonly reservation; | ||
static make<A1, E1, R1, E2, R2>(acquire: QIO<A1, E1, R1>, release: (a: A1) => QIO<void, E2, R2>): Managed<A1, E1 | E2, R1 & R2>; | ||
static make<A1, E1, R1, E2, R2>(acquire: QIO<A1, E1, R1>, release: (a: A1) => QIO<unknown, E2, R2>): Managed<A1, E1 | E2, R1 & R2>; | ||
static of<A1, E1, R1>(reservation: QIO<Reservation<A1, E1, R1>, E1, R1>): Managed<A1, E1, R1>; | ||
@@ -8,0 +8,0 @@ static zip<A1, E1, R1>(managed: Array<Managed<A1, E1, R1>>): Managed<A1[], E1, R1>; |
@@ -12,3 +12,3 @@ "use strict"; | ||
return Managed.of(acquire | ||
.map(a1 => Reservation_1.Reservation.of(QIO_1.QIO.resolve(a1).addEnv(), release(a1))) | ||
.map((a1) => Reservation_1.Reservation.of(QIO_1.QIO.resolve(a1).addEnv(), release(a1))) | ||
.addEnv()); | ||
@@ -22,6 +22,6 @@ } | ||
.reduce((a, b) => a.zipWith(b, (x, y) => x.prepend(y)), Managed.make(QIO_1.QIO.resolve(standard_data_structures_1.List.empty()).addEnv(), QIO_1.QIO.void)) | ||
.map(_ => _.asArray.reverse()); | ||
.map((_) => _.asArray.reverse()); | ||
} | ||
chain(fn) { | ||
return Managed.of(this.reservation.chain(r1 => r1.acquire.chain(a1 => fn(a1).reservation.map(r2 => { | ||
return Managed.of(this.reservation.chain((r1) => r1.acquire.chain((a1) => fn(a1).reservation.map((r2) => { | ||
const acquire = r2.acquire; | ||
@@ -33,6 +33,6 @@ const release = r2.release.and(r1.release); | ||
map(fn) { | ||
return Managed.of(this.reservation.map(r1 => Reservation_1.Reservation.of(r1.acquire.map(fn), r1.release))); | ||
return Managed.of(this.reservation.map((r1) => Reservation_1.Reservation.of(r1.acquire.map(fn), r1.release))); | ||
} | ||
use(fn) { | ||
return this.reservation.chain(R => R.acquire.bracket_(R.release)(fn)); | ||
return this.reservation.chain((R) => R.acquire.bracket_(R.release)(fn)); | ||
} | ||
@@ -43,5 +43,5 @@ use_(io) { | ||
zipWith(that, fn) { | ||
return this.chain(a1 => that.map(a2 => fn(a1, a2))); | ||
return this.chain((a1) => that.map((a2) => fn(a1, a2))); | ||
} | ||
} | ||
exports.Managed = Managed; |
@@ -13,7 +13,2 @@ import { Either } from 'standard-data-structures'; | ||
readonly i1?: unknown; | ||
get asEither(): QIO<Either<E1, A1>, never, R1>; | ||
get asInstruction(): Instruction; | ||
get env(): QIO<R1, never, R1>; | ||
get once(): QIO<QIO<A1, E1>, never, R1>; | ||
get void(): QIO<void, E1, R1>; | ||
static access<R, A>(cb: (R: R) => A): QIO<A, never, R>; | ||
@@ -60,6 +55,11 @@ static accessA<A, E, R>(fn: (A: CB<A>, E: CB<E>, R: R) => void): QIO<A, E, R>; | ||
constructor(tag: Tag, i0?: unknown, i1?: unknown); | ||
get asEither(): QIO<Either<E1, A1>, never, R1>; | ||
get asInstruction(): Instruction; | ||
get env(): QIO<R1, never, R1>; | ||
get once(): QIO<QIO<A1, E1>, never, R1>; | ||
get void(): QIO<void, E1, R1>; | ||
addEnv<R2>(): QIO<A1, E1, R1 & R2>; | ||
and<A2, E2, R2>(aFb: QIO<A2, E2, R2>): QIO<A2, E1 | E2, R1 & R2>; | ||
bracket<E2, R2>(release: (A1: A1) => QIO<void, E2, R2>): <A3, E3, R3>(usage: (A1: A1) => QIO<A3, E3, R3>) => QIO<A3, E1 | E2 | E3, R1 & R2 & R3>; | ||
bracket_<E2, R2>(release: QIO<void, E2, R2>): <A3, E3, R3>(usage: (A1: A1) => QIO<A3, E3, R3>) => QIO<A3, E1 | E2 | E3, R1 & R2 & R3>; | ||
bracket<E2, R2>(release: (A1: A1) => QIO<unknown, E2, R2>): <A3, E3, R3>(usage: (A1: A1) => QIO<A3, E3, R3>) => QIO<A3, E1 | E2 | E3, R1 & R2 & R3>; | ||
bracket_<E2, R2>(release: QIO<unknown, E2, R2>): <A3, E3, R3>(usage: (A1: A1) => QIO<A3, E3, R3>) => QIO<A3, E1 | E2 | E3, R1 & R2 & R3>; | ||
catch<A2, E2, R2>(aFb: (e: E1) => QIO<A2, E2, R2>): QIO<A1 | A2, E2, R1 & R2>; | ||
@@ -66,0 +66,0 @@ chain<A2, E2, R2>(aFb: (a: A1) => QIO<A2, E2, R2>): QIO<A2, E1 | E2, R1 & R2>; |
@@ -16,17 +16,2 @@ "use strict"; | ||
} | ||
get asEither() { | ||
return this.map(standard_data_structures_1.Either.right).catch(_ => QIO.resolve(standard_data_structures_1.Either.left(_))); | ||
} | ||
get asInstruction() { | ||
return this; | ||
} | ||
get env() { | ||
return QIO.access(prelude_1.Id); | ||
} | ||
get once() { | ||
return this.env.chain(env => Await_1.Await.of().map(AWT => AWT.set(this.provide(env)).and(AWT.get))); | ||
} | ||
get void() { | ||
return this.const(undefined); | ||
} | ||
static access(cb) { | ||
@@ -45,3 +30,3 @@ return new QIO(Instructions_1.Tag.Access, cb); | ||
static ap(qio, input) { | ||
return qio.map(ab => ab(input)); | ||
return qio.map((ab) => ab(input)); | ||
} | ||
@@ -58,2 +43,5 @@ static call(fn, ...args) { | ||
static chain(fa, aFb) { | ||
if (fa.tag === Instructions_1.Tag.Constant) { | ||
return aFb(fa.i0); | ||
} | ||
return new QIO(Instructions_1.Tag.Chain, fa, aFb); | ||
@@ -68,3 +56,3 @@ } | ||
static encaseP(cb) { | ||
return (...t) => QIO.runtime().chain(RTM => QIO.interruptible((res, rej) => RTM.scheduler.asap(() => { | ||
return (...t) => QIO.runtime().chain((RTM) => QIO.interruptible((res, rej) => RTM.scheduler.asap(() => { | ||
void cb(...t) | ||
@@ -106,2 +94,5 @@ .then(res) | ||
static map(fa, ab) { | ||
if (fa.tag === Instructions_1.Tag.Constant) { | ||
return QIO.resolve(ab(fa.i0)); | ||
} | ||
return new QIO(Instructions_1.Tag.Map, fa, ab); | ||
@@ -119,6 +110,6 @@ } | ||
}), QIO.env().and(QIO.lift(() => standard_data_structures_1.List.empty()))) | ||
.map(_ => _.asArray.reverse()); | ||
.map((_) => _.asArray.reverse()); | ||
} | ||
static parN(N, ios) { | ||
const itar = (list) => QIO.if(list.length === 0, QIO.resolve([]), QIO.par(list.slice(0, N)).chain(l1 => itar(list.slice(N, list.length)).map(l2 => l1.concat(l2)))); | ||
const itar = (list) => QIO.if(list.length === 0, QIO.resolve([]), QIO.par(list.slice(0, N)).chain((l1) => itar(list.slice(N, list.length)).map((l2) => l1.concat(l2)))); | ||
return itar(ios); | ||
@@ -146,7 +137,7 @@ } | ||
return ios | ||
.reduce((fList, f) => fList.chain(list => f.map(value => list.prepend(value))), QIO.lift(() => standard_data_structures_1.List.empty()).addEnv()) | ||
.map(_ => _.asArray); | ||
.reduce((fList, f) => fList.chain((list) => f.map((value) => list.prepend(value))), QIO.lift(() => standard_data_structures_1.List.empty()).addEnv()) | ||
.map((_) => _.asArray); | ||
} | ||
static timeout(value, duration) { | ||
return QIO.runtime().chain(RTM => QIO.interruptible(res => RTM.scheduler.delay(res, duration, value))); | ||
return QIO.runtime().chain((RTM) => QIO.interruptible((res) => RTM.scheduler.delay(res, duration, value))); | ||
} | ||
@@ -163,3 +154,3 @@ static try(cb) { | ||
static uninterruptible(fn) { | ||
return QIO.runtime().chain(RTM => QIO.interruptible((res, rej) => RTM.scheduler.asap(() => { | ||
return QIO.runtime().chain((RTM) => QIO.interruptible((res, rej) => RTM.scheduler.asap(() => { | ||
try { | ||
@@ -176,2 +167,17 @@ fn(res, rej); | ||
} | ||
get asEither() { | ||
return this.map(standard_data_structures_1.Either.right).catch((_) => QIO.resolve(standard_data_structures_1.Either.left(_))); | ||
} | ||
get asInstruction() { | ||
return this; | ||
} | ||
get env() { | ||
return QIO.access(prelude_1.Id); | ||
} | ||
get once() { | ||
return this.env.chain((env) => Await_1.Await.of().map((AWT) => AWT.set(this.provide(env)).and(AWT.get))); | ||
} | ||
get void() { | ||
return this.const(undefined); | ||
} | ||
addEnv() { | ||
@@ -184,5 +190,5 @@ return QIO.env().and(this); | ||
bracket(release) { | ||
return usage => this.chain(a1 => usage(a1) | ||
return (usage) => this.chain((a1) => usage(a1) | ||
.fork() | ||
.chain(F => F.await.and(release(a1)).chain(_ => F.join))); | ||
.chain((F) => F.await.and(release(a1)).chain((_) => F.join))); | ||
} | ||
@@ -205,3 +211,3 @@ bracket_(release) { | ||
do(io) { | ||
return this.chain(_ => io.const(_)); | ||
return this.chain((_) => io.const(_)); | ||
} | ||
@@ -218,3 +224,3 @@ encase(fn) { | ||
forkWith(runtime) { | ||
return QIO.env().chain(ENV => QIO.fork(this.provide(ENV), runtime)); | ||
return QIO.env().chain((ENV) => QIO.fork(this.provide(ENV), runtime)); | ||
} | ||
@@ -231,3 +237,3 @@ map(ab) { | ||
provideM(io) { | ||
return io.chain(ENV => this.provide(ENV)); | ||
return io.chain((ENV) => this.provide(ENV)); | ||
} | ||
@@ -238,24 +244,21 @@ provideSome(fn) { | ||
provideSomeM(qio) { | ||
return qio.chain(_ => this.provide(_)); | ||
return qio.chain((_) => this.provide(_)); | ||
} | ||
race(that) { | ||
return this.raceWith(that, (E, F) => F.abort.const(E), (E, F) => F.abort.const(E)).chain(E => QIO.fromExit(E)); | ||
return this.raceWith(that, (E, F) => F.abort.const(E), (E, F) => F.abort.const(E)).chain((E) => QIO.fromExit(E)); | ||
} | ||
raceWith(that, cb1, cb2) { | ||
return Await_1.Await.of().chain(done => { | ||
return Await_1.Await.of().chain((done) => { | ||
D('raceWith', 'await id:', done.id); | ||
return this.fork().zipWithM(that.fork(), (L, R) => { | ||
D('raceWith', 'fiber L.id', L.id, '& fiber R.id', R.id); | ||
const resume1 = L.await.chain(exit => { | ||
const resume1 = L.await.chain((exit) => { | ||
D('raceWith', 'L cb'); | ||
return done.set(cb1(exit, R)).const(true); | ||
}); | ||
const resume2 = R.await.chain(exit => { | ||
const resume2 = R.await.chain((exit) => { | ||
D('raceWith', 'R cb'); | ||
return done.set(cb2(exit, L)).const(true); | ||
}); | ||
return resume1 | ||
.fork() | ||
.and(resume2.fork()) | ||
.and(done.get); | ||
return resume1.fork().and(resume2.fork()).and(done.get); | ||
}); | ||
@@ -271,3 +274,3 @@ }); | ||
tapM(io) { | ||
return this.chain(_ => io(_).const(_)); | ||
return this.chain((_) => io(_).const(_)); | ||
} | ||
@@ -278,3 +281,3 @@ zip(that) { | ||
zipWith(that, c) { | ||
return this.chain(a1 => that.map(a2 => c(a1, a2))); | ||
return this.chain((a1) => that.map((a2) => c(a1, a2))); | ||
} | ||
@@ -285,5 +288,5 @@ zipWithM(that, c) { | ||
zipWithPar(that, c) { | ||
return this.raceWith(that, (E, F) => Exit_1.Exit.fold(E)(QIO.never(), value => F.join.map(_ => c(value, _)), cause => F.abort.and(QIO.reject(cause))), (E, F) => Exit_1.Exit.fold(E)(QIO.never(), value => F.join.map(_ => c(_, value)), cause => F.abort.and(QIO.reject(cause)))); | ||
return this.raceWith(that, (E, F) => Exit_1.Exit.fold(E)(QIO.never(), (value) => F.join.map((_) => c(value, _)), (cause) => F.abort.and(QIO.reject(cause))), (E, F) => Exit_1.Exit.fold(E)(QIO.never(), (value) => F.join.map((_) => c(_, value)), (cause) => F.abort.and(QIO.reject(cause)))); | ||
} | ||
} | ||
exports.QIO = QIO; |
import { QIO } from './QIO'; | ||
export declare class Queue<A = never> { | ||
readonly capacity: number; | ||
get asArray(): QIO<A[]>; | ||
get length(): QIO<number>; | ||
get take(): QIO<A>; | ||
static bounded<A>(capacity: number): QIO<Queue<A>>; | ||
static unbounded<A>(): QIO<Queue<A>>; | ||
private readonly id; | ||
private readonly O; | ||
private readonly Q; | ||
private readonly T; | ||
private constructor(); | ||
get asArray(): QIO<A[]>; | ||
get length(): QIO<number>; | ||
get take(): QIO<A>; | ||
get waitForSpace(): QIO<boolean>; | ||
private get stat(); | ||
offer(a: A): QIO<void>; | ||
offerAll(...a: A[]): QIO<void>; | ||
takeN(n: number): QIO<A[]>; | ||
private resolvePendingOffers; | ||
private resolvePendingTakes; | ||
} |
@@ -5,11 +5,31 @@ "use strict"; | ||
const standard_data_structures_1 = require("standard-data-structures"); | ||
const IDGenerator_1 = require("../internals/IDGenerator"); | ||
const Await_1 = require("./Await"); | ||
const QIO_1 = require("./QIO"); | ||
const QUEUE_ID = new IDGenerator_1.IDGenerator(); | ||
const D = (scope, f, ...t) => debug_1.debug('qio:queue')(scope, f, ...t); | ||
const consume = (T) => { | ||
const R = new Array(); | ||
while (T.length !== 0) { | ||
const item = T.shift(); | ||
if (standard_data_structures_1.Option.isSome(item)) { | ||
R.push(item.value); | ||
} | ||
} | ||
return R; | ||
}; | ||
class Queue { | ||
constructor(capacity) { | ||
this.capacity = capacity; | ||
this.id = QUEUE_ID.create(); | ||
this.O = standard_data_structures_1.DoublyLinkedList.of(); | ||
this.Q = standard_data_structures_1.DoublyLinkedList.of(); | ||
this.T = standard_data_structures_1.DoublyLinkedList.of(); | ||
} | ||
static bounded(capacity) { | ||
return QIO_1.QIO.lift(() => new Queue(capacity)); | ||
} | ||
static unbounded() { | ||
return Queue.bounded(Number.MAX_SAFE_INTEGER); | ||
} | ||
get asArray() { | ||
@@ -23,44 +43,56 @@ return QIO_1.QIO.lift(() => this.Q.asArray); | ||
return QIO_1.QIO.tryM(() => { | ||
D('%i this.take() %O', this.id, this.stat); | ||
const sz = this.Q.shift(); | ||
if (standard_data_structures_1.Option.isSome(sz)) { | ||
return QIO_1.QIO.resolve(sz.value); | ||
return this.resolvePendingOffers().const(sz.value); | ||
} | ||
return QIO_1.QIO.flatten(Await_1.Await.of().chain(QIO_1.QIO.encase(awt => { | ||
return Await_1.Await.of().chain(QIO_1.QIO.encaseM((awt) => { | ||
this.T.add(awt); | ||
return awt.get; | ||
}))); | ||
})); | ||
}).do(this.resolvePendingOffers()); | ||
} | ||
get waitForSpace() { | ||
return Await_1.Await.of().encaseM((AWT) => { | ||
this.O.add(AWT); | ||
return AWT.get; | ||
}); | ||
} | ||
static bounded(capacity) { | ||
return QIO_1.QIO.lift(() => new Queue(capacity)); | ||
get stat() { | ||
return { | ||
pOffers: this.O.length, | ||
pTakes: this.T.length, | ||
queue: this.Q.length, | ||
}; | ||
} | ||
static unbounded() { | ||
return Queue.bounded(Number.MAX_SAFE_INTEGER); | ||
} | ||
offer(a) { | ||
return QIO_1.QIO.tryM(() => { | ||
if (this.T.length === 0) { | ||
this.Q.add(a); | ||
D('offer', 'Q.add()', a); | ||
return QIO_1.QIO.void(); | ||
D('%i this.offer(%O) %O', this.id, a, this.stat); | ||
if (this.Q.length === this.capacity) { | ||
return this.waitForSpace.and(this.offer(a)); | ||
} | ||
const io = new Array(); | ||
while (this.T.length !== 0) { | ||
const item = this.T.shift(); | ||
if (standard_data_structures_1.Option.isSome(item)) { | ||
D('offer', 'Q.shift()', a); | ||
io.push(item.value.set(QIO_1.QIO.resolve(a))); | ||
} | ||
} | ||
return QIO_1.QIO.seq(io).void; | ||
this.Q.add(a); | ||
return this.resolvePendingTakes(); | ||
}); | ||
} | ||
offerAll(...a) { | ||
return QIO_1.QIO.seq(a.map(_ => this.offer(_))).void; | ||
return QIO_1.QIO.seq(a.map((_) => this.offer(_))).void; | ||
} | ||
takeN(n) { | ||
const itar = (i, list) => QIO_1.QIO.if0()(() => i === n, () => QIO_1.QIO.resolve(list), () => this.take.chain(_ => itar(i + 1, list.prepend(_)))); | ||
return itar(0, standard_data_structures_1.List.empty()).map(_ => _.asArray.reverse()); | ||
const itar = (i, list) => QIO_1.QIO.if0()(() => i === n, () => QIO_1.QIO.resolve(list), () => this.take.chain((_) => itar(i + 1, list.prepend(_)))); | ||
return itar(0, standard_data_structures_1.List.empty()).map((_) => _.asArray.reverse()); | ||
} | ||
resolvePendingOffers() { | ||
return QIO_1.QIO.seq(consume(this.O).map((_) => _.setTo(true))).void; | ||
} | ||
resolvePendingTakes() { | ||
if (this.T.length > 0) { | ||
const aa = this.Q.shift(); | ||
if (standard_data_structures_1.Option.isSome(aa)) { | ||
return QIO_1.QIO.seq(consume(this.T).map((_) => _.setTo(aa.value))).void; | ||
} | ||
} | ||
return QIO_1.QIO.void(); | ||
} | ||
} | ||
exports.Queue = Queue; |
import { QIO } from './QIO'; | ||
export declare class Reservation<A1, E1, R1> { | ||
readonly acquire: QIO<A1, E1, R1>; | ||
readonly release: QIO<void, E1, R1>; | ||
static of<A1, E1, R1, E2, R2>(acquire: QIO<A1, E1, R1>, release: QIO<void, E2, R2>): Reservation<A1, E1 | E2, R1 & R2>; | ||
readonly release: QIO<unknown, E1, R1>; | ||
static of<A1, E1, R1, E2, R2>(acquire: QIO<A1, E1, R1>, release: QIO<unknown, E2, R2>): Reservation<A1, E1 | E2, R1 & R2>; | ||
private constructor(); | ||
} |
import { QIO } from './QIO'; | ||
export declare class Snapshot<T = string | number> { | ||
readonly timelineData: [T, number][]; | ||
get timeline(): string[]; | ||
readonly timelineData: [T, number][]; | ||
mark(value: T): QIO<T>; | ||
} |
@@ -11,6 +11,6 @@ "use strict"; | ||
get timeline() { | ||
return this.timelineData.map(_ => _.join('@')); | ||
return this.timelineData.map((_) => _.join('@')); | ||
} | ||
mark(value) { | ||
return QIO_1.QIO.runtime().chain(RTM => QIO_1.QIO.lift(() => { | ||
return QIO_1.QIO.runtime().chain((RTM) => QIO_1.QIO.lift(() => { | ||
D('mark %O', value); | ||
@@ -17,0 +17,0 @@ this.timelineData.push([value, RTM.scheduler.now()]); |
@@ -18,3 +18,3 @@ "use strict"; | ||
return new Promise((res, rej) => { | ||
this.unsafeExecute(io, exit => Exit_1.Exit.fold(exit)(undefined, res, rej)); | ||
this.unsafeExecute(io, (exit) => Exit_1.Exit.fold(exit)(undefined, res, rej)); | ||
}); | ||
@@ -21,0 +21,0 @@ } |
@@ -25,3 +25,3 @@ "use strict"; | ||
let result; | ||
this.unsafeExecute(io, _ => (result = _)); | ||
this.unsafeExecute(io, (_) => (result = _)); | ||
this.scheduler.run(); | ||
@@ -28,0 +28,0 @@ return result; |
@@ -18,5 +18,5 @@ { | ||
}, | ||
"version": "31.0.0", | ||
"version": "31.1.0", | ||
"dependencies": { | ||
"@qio/prelude": "^31.0.0", | ||
"@qio/prelude": "^31.1.0", | ||
"debug": "^4.1.1", | ||
@@ -28,9 +28,9 @@ "in-node": "^1.0.0", | ||
"devDependencies": { | ||
"@types/chai": "^4.2.7", | ||
"@types/chai": "^4.2.11", | ||
"@types/chai-spies": "^1.0.1", | ||
"@types/debug": "^4.1.5", | ||
"@types/mocha": "^5.2.7", | ||
"@types/mocha": "^7.0.2", | ||
"chai": "^4.2.0", | ||
"chai-spies": "^1.0.0", | ||
"mocha": "^6.2.2" | ||
"mocha": "^7.1.1" | ||
}, | ||
@@ -40,3 +40,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "64488449e0b666bc87ede148799b191b975d74f2" | ||
"gitHead": "52c27a96aae49d1508ca49f4f8122cf1ca47739f" | ||
} |
80056
62
1825
Updated@qio/prelude@^31.1.0