UNPKG

@effect-ts/system

Version:

Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.

1,157 lines (939 loc) 38.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unsafeCurrentFiber = exports.currentFiber = exports.TracingExit = exports.Stack = exports.InterruptExit = exports.HandlerFrame = exports.FiberContext = exports.ApplyFrame = void 0; var Cause = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Cause/core.js")); var _errors = /*#__PURE__*/require("../Cause/errors.js"); var A = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Collections/Immutable/Array/index.js")); var L = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Collections/Immutable/List/index.js")); var _exclForEach = /*#__PURE__*/require("../Effect/excl-forEach.js"); var _primitives = /*#__PURE__*/require("../Effect/primitives.js"); var E = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Either/index.js")); var Exit = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Exit/api.js")); var FR = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberRef/fiberRef.js")); var update = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberRef/update.js")); var _index4 = /*#__PURE__*/require("../Function/index.js"); var O = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Option/index.js")); var Scope = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Scope/index.js")); var St = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Structural/index.js")); var Sup = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Supervisor/index.js")); var _index9 = /*#__PURE__*/require("../Support/AtomicReference/index.js"); var _index10 = /*#__PURE__*/require("../Support/RingBuffer/index.js"); var _index11 = /*#__PURE__*/require("../Support/Scheduler/index.js"); var X = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../XPure/index.js")); var T = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./_internal/effect.js")); var Fiber = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./core.js")); var _state = /*#__PURE__*/require("./state.js"); var Status = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./status.js")); var _tracing = /*#__PURE__*/require("./tracing.js"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } // ets_tracing: off // cause // effect // either // exit // fiberRef // option // supervisor / scope // support // fiber class Stack { constructor(value, previous) { this.value = value; this.previous = previous; } } exports.Stack = Stack; class InterruptExit { constructor(apply, trace) { this.apply = apply; this.trace = trace; this._tag = "InterruptExit"; } } exports.InterruptExit = InterruptExit; class TracingExit { constructor(apply, trace) { this.apply = apply; this.trace = trace; this._tag = "TracingExit"; } } exports.TracingExit = TracingExit; class HandlerFrame { constructor(apply, trace) { this.apply = apply; this.trace = trace; this._tag = "HandlerFrame"; } } exports.HandlerFrame = HandlerFrame; class ApplyFrame { constructor(apply, trace) { this.apply = apply; this.trace = trace; this._tag = "ApplyFrame"; } } exports.ApplyFrame = ApplyFrame; const currentFiber = /*#__PURE__*/new _index9.AtomicReference(null); exports.currentFiber = currentFiber; const unsafeCurrentFiber = () => O.fromNullable(currentFiber.get); exports.unsafeCurrentFiber = unsafeCurrentFiber; const noop = /*#__PURE__*/O.some(_index4.constVoid); class FiberContext { constructor(fiberId, startEnv, startIStatus, fiberRefLocals, supervisor0, openScope, maxOp, reportFailure, platform, parentTrace, initialTracingStatus) { this.fiberId = fiberId; this.startEnv = startEnv; this.startIStatus = startIStatus; this.fiberRefLocals = fiberRefLocals; this.supervisor0 = supervisor0; this.openScope = openScope; this.maxOp = maxOp; this.reportFailure = reportFailure; this.platform = platform; this.parentTrace = parentTrace; this.initialTracingStatus = initialTracingStatus; this._tag = "RuntimeFiber"; this.state = new _index9.AtomicReference((0, _state.initial)()); this.asyncEpoch = 0 | 0; this.stack = undefined; this.environments = new Stack(this.startEnv); this.interruptStatus = new Stack(this.startIStatus.toBoolean); this.supervisors = new Stack(this.supervisor0); this.forkScopeOverride = undefined; this.scopeKey = undefined; this.traceStatusEnabled = this.platform.value.traceExecution || this.platform.value.traceStack; this.traceStatusStack = this.traceStatusEnabled ? new Stack(this.initialTracingStatus) : undefined; this.executionTraces = this.traceStatusEnabled ? new _index10.RingBuffer(this.platform.value.executionTraceLength) : undefined; this.stackTraces = this.traceStatusEnabled ? new _index10.RingBuffer(this.platform.value.stackTraceLength, x => x._tag === "NoLocation") : undefined; this.interruptExit = new InterruptExit(v => { if (this.isInterruptible) { this.popInterruptStatus(); return T.succeed(v); } else { return T.succeedWith(() => { this.popInterruptStatus(); return v; }); } }); this.tracingExit = new TracingExit(v => { this.popTracingStatus(); return new _primitives.ISucceed(v); }); this.evaluateNow = this.evaluateNow.bind(this); } get [St.hashSym]() { return St.hash(this.id); } [St.equalsSym](that) { return that instanceof FiberContext && St.equals(this.id, that.id); } get poll() { return T.succeedWith(() => this.poll0()); } addTrace(trace) { if (this.inTracingRegion && trace) { this.executionTraces.push(new _tracing.SourceLocation(trace)); } } addTraceValue(trace) { if (this.inTracingRegion && trace._tag === "SourceLocation") { this.executionTraces.push(trace); } } getRef(fiberRef) { return T.succeedWith(() => this.fiberRefLocals.get(fiberRef) || fiberRef.initial); } poll0() { const state = this.state.get; switch (state._tag) { case "Executing": { return O.none; } case "Done": { return O.some(state.value); } } } popTracingStatus() { var _a; this.traceStatusStack = (_a = this.traceStatusStack) === null || _a === void 0 ? void 0 : _a.previous; } pushTracingStatus(flag) { this.traceStatusStack = new Stack(flag, this.traceStatusStack); } get isInterruptible() { return this.interruptStatus ? this.interruptStatus.value : true; } get isInterrupted() { return !Cause.isEmpty(this.state.get.interrupted); } get isInterrupting() { return (0, _state.interrupting)(this.state.get); } get shouldInterrupt() { return this.isInterrupted && this.isInterruptible && !this.isInterrupting; } get isStackEmpty() { return !this.stack; } get id() { return this.fiberId; } pushContinuation(k) { if (this.platform.value.traceStack && this.inTracingRegion) { this.stackTraces.push((0, _tracing.traceLocation)(k.trace)); } this.stack = new Stack(k, this.stack); } popStackTrace() { this.stackTraces.pop(); } popContinuation() { var _a, _b; const current = (_a = this.stack) === null || _a === void 0 ? void 0 : _a.value; this.stack = (_b = this.stack) === null || _b === void 0 ? void 0 : _b.previous; return current; } pushEnv(k) { this.environments = new Stack(k, this.environments); } popEnv() { var _a, _b; const current = (_a = this.environments) === null || _a === void 0 ? void 0 : _a.value; this.environments = (_b = this.environments) === null || _b === void 0 ? void 0 : _b.previous; return current; } pushInterruptStatus(flag) { this.interruptStatus = new Stack(flag, this.interruptStatus); } popInterruptStatus() { var _a, _b; const current = (_a = this.interruptStatus) === null || _a === void 0 ? void 0 : _a.value; this.interruptStatus = (_b = this.interruptStatus) === null || _b === void 0 ? void 0 : _b.previous; return current; } runAsync(k) { const v = this.register0(xx => k(Exit.flatten(xx))); if (v) { k(v); } } /** * Unwinds the stack, looking for the first error handler, and exiting * interruptible / uninterruptible regions. */ unwindStack() { let unwinding = true; let discardedFolds = false; // Unwind the stack, looking for an error handler: while (unwinding && !this.isStackEmpty) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const frame = this.popContinuation(); switch (frame._tag) { case "InterruptExit": { this.popInterruptStatus(); break; } case "TracingExit": { this.popTracingStatus(); break; } case "Fold": { if (this.platform.value.traceStack && this.inTracingRegion) { this.popStackTrace(); } if (!this.shouldInterrupt) { // Push error handler back onto the stack and halt iteration: this.pushContinuation(new HandlerFrame(frame.failure, frame.trace)); unwinding = false; } else { discardedFolds = true; } break; } default: { if (this.platform.value.traceStack && this.inTracingRegion) { this.popStackTrace(); } } } } return discardedFolds; } register0(k) { const oldState = this.state.get; switch (oldState._tag) { case "Done": { return oldState.value; } case "Executing": { const observers = [k, ...oldState.observers]; this.state.set(new _state.FiberStateExecuting(oldState.status, observers, oldState.interrupted)); return null; } } } nextInstr(value) { if (!this.isStackEmpty) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const k = this.popContinuation(); if (this.inTracingRegion && this.platform.value.traceExecution) { this.addTrace(k.trace); } if (this.platform.value.traceStack && k._tag !== "InterruptExit" && k._tag !== "TracingExit") { this.popStackTrace(); } return k.apply(value); } else { return this.done(Exit.succeed(value)); } } notifyObservers(v, observers) { const result = Exit.succeed(v); observers.slice(0).reverse().forEach(k => k(result)); } observe0(k) { const x = this.register0(k); if (x != null) { return O.some(T.succeed(x)); } return O.none; } get await() { return T.effectMaybeAsyncInterruptBlockingOn(k => { const cb = x => k(T.done(x)); return O.fold_(this.observe0(cb), () => E.left(T.succeedWith(() => this.interruptObserver(cb))), E.right); }, [this.fiberId]); } interruptObserver(k) { const oldState = this.state.get; if (oldState._tag === "Executing") { const observers = oldState.observers.filter(o => o !== k); this.state.set(new _state.FiberStateExecuting(oldState.status, observers, oldState.interrupted)); } } interruptAs(fiberId) { const interruptedCause = Cause.interrupt(fiberId); return T.suspend(() => { const oldState = this.state.get; if (oldState._tag === "Executing" && oldState.status._tag === "Suspended" && oldState.status.interruptible && !(0, _state.interrupting)(oldState)) { const newCause = Cause.combineSeq(oldState.interrupted, interruptedCause); this.state.set(new _state.FiberStateExecuting(Status.withInterrupting(true)(oldState.status), oldState.observers, newCause)); this.evaluateLater(T.interruptAs(fiberId)); } else if (oldState._tag === "Executing") { const newCause = Cause.combineSeq(oldState.interrupted, interruptedCause); this.state.set(new _state.FiberStateExecuting(oldState.status, oldState.observers, newCause)); } return this.await; }); } done(v) { const oldState = this.state.get; switch (oldState._tag) { case "Done": { // Already done return undefined; } case "Executing": { if (this.openScope.scope.unsafeClosed) { /* * We are truly "done" because all the children of this fiber have terminated, * and there are no more pending effects that we have to execute on the fiber. */ this.state.set(new _state.FiberStateDone(v)); this.reportUnhandled(v); this.notifyObservers(v, oldState.observers); return undefined; } else { /* * We are not done yet, because we have to close the scope of the fiber. */ this.state.set(new _state.FiberStateExecuting(Status.toFinishing(oldState.status), oldState.observers, oldState.interrupted)); this.setInterrupting(true); return T.chain_(this.openScope.close(v), () => T.done(v)); } } } } reportUnhandled(exit) { if (exit._tag === "Failure") { this.reportFailure(exit.cause); } } setInterrupting(value) { const oldState = this.state.get; switch (oldState._tag) { case "Executing": { this.state.set(new _state.FiberStateExecuting(Status.withInterrupting(value)(oldState.status), oldState.observers, oldState.interrupted)); return; } case "Done": { return; } } } enterAsync(epoch, blockingOn) { const oldState = this.state.get; switch (oldState._tag) { case "Done": { throw new _errors.RuntimeError(`Unexpected fiber completion ${this.fiberId}`); } case "Executing": { const newState = new _state.FiberStateExecuting(new Status.Suspended(oldState.status, this.isInterruptible, epoch, blockingOn), oldState.observers, oldState.interrupted); this.state.set(newState); if (this.shouldInterrupt) { // Fiber interrupted, so go back into running state: this.exitAsync(epoch); return T.halt(this.state.get.interrupted); } else { return undefined; } } } } exitAsync(epoch) { const oldState = this.state.get; switch (oldState._tag) { case "Done": { return false; } case "Executing": { if (oldState.status._tag === "Suspended" && epoch === oldState.status.epoch) { this.state.set(new _state.FiberStateExecuting(oldState.status.previous, oldState.observers, oldState.interrupted)); return true; } else { return false; } } } } resumeAsync(epoch) { return _ => { if (this.exitAsync(epoch)) { this.evaluateLater(_); } }; } evaluateLater(i0) { (0, _index11.defaultScheduler)(() => this.evaluateNow(i0)); } get scope() { return this.openScope.scope; } get status() { return T.succeed(this.state.get.status); } fork(i0, forkScope, reportFailure) { var _a, _b; const childFiberRefLocals = new Map(); this.fiberRefLocals.forEach((v, k) => { childFiberRefLocals.set(k, k.fork(v)); }); const parentScope = O.getOrElse_(forkScope._tag === "Some" ? forkScope : ((_a = this.forkScopeOverride) === null || _a === void 0 ? void 0 : _a.value) || O.none, () => this.scope); const currentEnv = ((_b = this.environments) === null || _b === void 0 ? void 0 : _b.value) || {}; const currentSup = this.supervisors.value; const childId = Fiber.newFiberId(); const childScope = Scope.unsafeMakeScope(); const ancestry = this.inTracingRegion && (this.platform.value.traceExecution || this.platform.value.traceStack) ? O.some(this.cutAncestryTrace(this.captureTrace())) : O.none; const childContext = new FiberContext(childId, currentEnv, Fiber.interruptStatus(this.isInterruptible), childFiberRefLocals, currentSup, childScope, this.maxOp, O.getOrElse_(reportFailure, () => this.reportFailure), this.platform, ancestry, this.inTracingRegion); if (currentSup !== Sup.none) { currentSup.unsafeOnStart(currentEnv, i0, O.some(this), childContext); childContext.onDone(exit => { currentSup.unsafeOnEnd(Exit.flatten(exit), childContext); }); } const toExecute = this.parentScopeOp(parentScope, childContext, i0); childContext.evaluateLater(toExecute); return childContext; } parentScopeOp(parentScope, childContext, i0) { if (parentScope !== Scope.globalScope) { const exitOrKey = parentScope.unsafeEnsure(exit => T.suspend(() => { const _interruptors = exit._tag === "Failure" ? Cause.interruptors(exit.cause) : []; const head = _interruptors[0]; if (head) { return childContext.interruptAs(head); } else { return childContext.interruptAs(this.fiberId); } })); return E.fold_(exitOrKey, exit => { switch (exit._tag) { case "Failure": { return T.interruptAs(O.getOrElse_(A.head(Array.from(Cause.interruptors(exit.cause))), () => this.fiberId)); } case "Success": { return T.interruptAs(this.fiberId); } } }, key => { childContext.scopeKey = key; // Remove the finalizer key from the parent scope when the child fiber // terminates: childContext.onDone(() => { parentScope.unsafeDeny(key); }); return i0; }); } else { return i0; } } onDone(k) { const oldState = this.state.get; switch (oldState._tag) { case "Done": { k(Exit.succeed(oldState.value)); return; } case "Executing": { this.state.set(new _state.FiberStateExecuting(oldState.status, [k, ...oldState.observers], oldState.interrupted)); } } } getDescriptor() { return new Fiber.Descriptor(this.fiberId, this.state.get.status, Cause.interruptors(this.state.get.interrupted), Fiber.interruptStatus(this.isInterruptible), this.scope); } complete(winner, loser, cont, winnerExit, ab, cb) { if (ab.compareAndSet(true, false)) { switch (winnerExit._tag) { case "Failure": { cb(cont(winnerExit, loser)); break; } case "Success": { cb(T.chain_(winner.inheritRefs, () => cont(winnerExit, loser))); break; } } } } get inheritRefs() { return T.suspend(() => { const locals = this.fiberRefLocals; if (locals.size === 0) { return T.unit; } else { return (0, _exclForEach.forEachUnit_)(locals, ([fiberRef, value]) => update.update_(fiberRef, old => fiberRef.join(old, value))); } }); } get inTracingRegion() { return this.traceStatusStack ? this.traceStatusStack.value : this.initialTracingStatus; } raceWithImpl(race) { const raceIndicator = new _index9.AtomicReference(true); const left = this.fork(race.left, race.scope, noop); const right = this.fork(race.right, race.scope, noop); return T.effectAsyncBlockingOn(cb => { const leftRegister = left.register0(exit => { switch (exit._tag) { case "Failure": { this.complete(left, right, race.leftWins, exit, raceIndicator, cb); break; } case "Success": { this.complete(left, right, race.leftWins, exit.value, raceIndicator, cb); break; } } }); if (leftRegister != null) { this.complete(left, right, race.leftWins, leftRegister, raceIndicator, cb); } else { const rightRegister = right.register0(exit => { switch (exit._tag) { case "Failure": { this.complete(right, left, race.rightWins, exit, raceIndicator, cb); break; } case "Success": { this.complete(right, left, race.rightWins, exit.value, raceIndicator, cb); break; } } }); if (rightRegister != null) { this.complete(right, left, race.rightWins, rightRegister, raceIndicator, cb); } } }, [left.fiberId, right.fiberId], race.trace); } captureTrace() { const exec = this.executionTraces ? this.executionTraces.listReverse : L.empty(); const stack = this.stackTraces ? this.stackTraces.listReverse : L.empty(); return new _tracing.Trace(this.id, exec, stack, this.parentTrace); } cutAncestryTrace(trace) { const maxExecLength = this.platform.value.ancestorExecutionTraceLength; const maxStackLength = this.platform.value.ancestorStackTraceLength; const maxAncestors = this.platform.value.ancestryLength - 1; const truncated = (0, _tracing.truncatedParentTrace)(trace, maxAncestors); return new _tracing.Trace(trace.fiberId, L.take_(trace.executionTrace, maxExecLength), L.take_(trace.stackTrace, maxStackLength), truncated); } evaluateNow(i0) { var _a, _b; try { // eslint-disable-next-line prefer-const let current = i0; currentFiber.set(this); while (current != null) { try { let opCount = 0; while (current != null) { // Check to see if the fiber should continue executing or not: if (!this.shouldInterrupt) { // Fiber does not need to be interrupted, but might need to yield: if (opCount === this.maxOp) { this.evaluateLater(current); current = undefined; } else { // Fiber is neither being interrupted nor needs to yield. Execute // the next instruction in the program: switch (current._tag) { case "FlatMap": { this.pushContinuation(new ApplyFrame(current.f, current.trace)); current = current.val; break; } case "XPure": { const result = X.runEither(X.provideAll_(current, ((_a = this.environments) === null || _a === void 0 ? void 0 : _a.value) || {})); current = result._tag === "Left" ? new _primitives.IFail(t => Cause.traced(Cause.fail(result.left), t())) : new _primitives.ISucceed(result.right); break; } case "TracingStatus": { if (this.traceStatusStack) { this.pushTracingStatus(current.flag); this.stack = new Stack(this.tracingExit, this.stack); } current = current.effect; break; } case "CheckTracingStatus": { current = current.f(this.inTracingRegion); break; } case "Trace": { current = this.nextInstr(this.captureTrace()); break; } case "Tracer": { current = current.f(trace => { if (trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(trace); } }); break; } case "Succeed": { if (current.trace && this.platform.value.traceEffects && this.inTracingRegion) { this.addTrace(current.trace); } current = this.nextInstr(current.val); break; } case "EffectTotal": { if (current.trace && this.platform.value.traceEffects && this.inTracingRegion) { this.addTrace(current.trace); } current = this.nextInstr(current.effect()); break; } case "Fail": { if (current.trace && this.platform.value.traceEffects && this.inTracingRegion) { this.addTrace(current.trace); } const fullCause = current.fill(() => this.captureTrace()); const discardedFolds = this.unwindStack(); const maybeRedactedCause = discardedFolds ? // We threw away some error handlers while unwinding the stack because // we got interrupted during this instruction. So it's not safe to return // typed failures from cause0, because they might not be typed correctly. // Instead, we strip the typed failures, and return the remainders and // the interruption. Cause.stripFailures(fullCause) : fullCause; if (this.isStackEmpty) { // Error not caught, stack is empty: const cause = () => { const interrupted = this.state.get.interrupted; const causeAndInterrupt = !Cause.contains(interrupted)(maybeRedactedCause) ? Cause.combineSeq(maybeRedactedCause, interrupted) : maybeRedactedCause; return causeAndInterrupt; }; this.setInterrupting(true); current = this.done(Exit.halt(cause())); } else { this.setInterrupting(false); // Error caught, next continuation on the stack will deal // with it, so we just have to compute it here: current = this.nextInstr(maybeRedactedCause); } break; } case "Platform": { if (current.trace && this.inTracingRegion && this.platform.value.traceExecution) { this.addTrace(current.trace); } current = current.f(this.platform); break; } case "Fold": { this.pushContinuation(current); current = current.value; break; } case "InterruptStatus": { if (current.trace && this.inTracingRegion && this.platform.value.traceExecution) { this.addTrace(current.trace); } this.pushInterruptStatus(current.flag.toBoolean); this.stack = new Stack(this.interruptExit, this.stack); current = current.effect; break; } case "CheckInterrupt": { if (current.trace && this.inTracingRegion && this.platform.value.traceExecution) { this.addTrace(current.trace); } current = current.f(Fiber.interruptStatus(this.isInterruptible)); break; } case "EffectPartial": { const c = current; try { if (c.trace && this.inTracingRegion && this.platform.value.traceEffects) { this.addTrace(c.trace); } current = this.nextInstr(c.effect()); } catch (e) { current = T.fail(c.onThrow(e)); } break; } case "EffectAsync": { const epoch = this.asyncEpoch; this.asyncEpoch = epoch + 1; const c = current; current = this.enterAsync(epoch, c.blockingOn); if (!current) { const k = c.register; if (c.trace && this.platform.value.traceEffects && this.inTracingRegion) { this.addTrace(c.trace); } const h = k(this.resumeAsync(epoch)); switch (h._tag) { case "None": { current = undefined; break; } case "Some": { if (this.exitAsync(epoch)) { current = h.value; } else { current = undefined; } } } } break; } case "Fork": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = this.nextInstr(this.fork(current.value, current.scope, current.reportFailure)); break; } case "Descriptor": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = current.f(this.getDescriptor()); break; } case "Yield": { current = undefined; this.evaluateLater(T.unit); break; } case "Read": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = current.f(this.environments ? this.environments.value : {}); break; } case "Provide": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } const c = current; current = T.bracket_(T.succeedWith(() => { this.pushEnv(c.r); }), () => c.next, () => T.succeedWith(() => { this.popEnv(); })); break; } case "Suspend": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = current.factory(this.platform, this.fiberId); break; } case "SuspendPartial": { const c = current; try { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = c.factory(this.platform, this.fiberId); } catch (e) { current = T.fail(c.onThrow(e)); } break; } case "FiberRefNew": { const fiberRef = new FR.Runtime(current.initial, current.onFork, current.onJoin); this.fiberRefLocals.set(fiberRef, current.initial); current = this.nextInstr(fiberRef); break; } case "FiberRefModify": { const c = current; const oldValue = O.fromNullable(this.fiberRefLocals.get(c.fiberRef)); if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } const { tuple: [result, newValue] } = current.f(O.getOrElse_(oldValue, () => c.fiberRef.initial)); this.fiberRefLocals.set(c.fiberRef, newValue); current = this.nextInstr(result); break; } case "RaceWith": { current = this.raceWithImpl(current); break; } case "Supervise": { if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } const c = current; const lastSupervisor = this.supervisors.value; const newSupervisor = c.supervisor.and(lastSupervisor); const push = T.succeedWith(() => { this.supervisors = new Stack(newSupervisor, this.supervisors); }); const pop = T.succeedWith(() => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.supervisors = this.supervisors.previous; }); current = T.bracket_(push, () => c.effect, () => pop); break; } case "GetForkScope": { const c = current; if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } current = c.f(O.getOrElse_(((_b = this.forkScopeOverride) === null || _b === void 0 ? void 0 : _b.value) || O.none, () => this.scope)); break; } case "OverrideForkScope": { const c = current; if (current.trace && this.platform.value.traceExecution && this.inTracingRegion) { this.addTrace(current.trace); } const push = T.succeedWith(() => { this.forkScopeOverride = new Stack(c.forkScope, this.forkScopeOverride); }); const pop = T.succeedWith(() => { var _a; this.forkScopeOverride = (_a = this.forkScopeOverride) === null || _a === void 0 ? void 0 : _a.previous; }); current = T.bracket_(push, () => c.effect, () => pop); break; } default: { throw new _errors.RuntimeError(`operation not supported: ${JSON.stringify(current)}`); } } } } else { current = T.halt(this.state.get.interrupted); this.setInterrupting(true); } opCount += 1; } } catch (e) { this.setInterrupting(true); current = T.die(e); } } } finally { currentFiber.set(null); } } } exports.FiberContext = FiberContext; //# sourceMappingURL=context.js.map