"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.gen = exports.GenManaged = void 0;
// ets_tracing: off
const Effect_1 = require("../../Effect");
const fromEither_1 = require("../../Effect/fromEither");
const getOrFail_1 = require("../../Effect/getOrFail");
const Function_1 = require("../../Function");
const Utils_1 = require("../../Utils");
const core_1 = require("../core");
const fromEffect_1 = require("../fromEffect");
const managed_1 = require("../managed");
const succeed_1 = require("../succeed");
const suspend_1 = require("./suspend");
class GenManaged {
    constructor(effect, trace) {
        this.effect = effect;
        this.trace = trace;
    }
    *[Symbol.iterator]() {
        return yield this;
    }
}
exports.GenManaged = GenManaged;
const adapter = (_, __, ___) => {
    if ((0, Utils_1.isTag)(_)) {
        return new GenManaged((0, fromEffect_1.fromEffect)((0, Effect_1.accessService)(_)(Function_1.identity)), __);
    }
    if ((0, Utils_1.isEither)(_)) {
        return new GenManaged((0, fromEffect_1.fromEffect)((0, fromEither_1.fromEither)(() => _)), __);
    }
    if ((0, Utils_1.isOption)(_)) {
        if (typeof __ === "function") {
            return new GenManaged(__
                ? _._tag === "None"
                    ? (0, core_1.fail)(__())
                    : (0, succeed_1.succeed)(_.value)
                : (0, fromEffect_1.fromEffect)((0, getOrFail_1.getOrFail)(_)), ___);
        }
        return new GenManaged((0, fromEffect_1.fromEffect)((0, getOrFail_1.getOrFail)(_)), __);
    }
    if (_ instanceof managed_1.ManagedImpl) {
        return new GenManaged(_, __);
    }
    return new GenManaged((0, fromEffect_1.fromEffect)(_), __);
};
function gen(f) {
    return (0, suspend_1.suspend)(() => {
        const iterator = f(adapter);
        const state = iterator.next();
        function run(state) {
            if (state.done) {
                return (0, succeed_1.succeed)(state.value);
            }
            return (0, core_1.chain_)((0, suspend_1.suspend)(() => state.value["effect"], state.value.trace), (val) => {
                const next = iterator.next(val);
                return run(next);
            });
        }
        return run(state);
    });
}
exports.gen = gen;
//# sourceMappingURL=gen.js.map