"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.gen = exports.GenSync = void 0;
// ets_tracing: off
/**
 * inspired by https://github.com/tusharmath/qio/pull/22 (revised)
 */
const commons_1 = require("../Effect/commons");
const Function_1 = require("../Function");
const GlobalExceptions_1 = require("../GlobalExceptions");
const Utils_1 = require("../Utils");
const core_1 = require("./core");
const has_1 = require("./has");
class GenSync {
    constructor(effect) {
        this.effect = effect;
    }
    *[Symbol.iterator]() {
        return yield this;
    }
}
exports.GenSync = GenSync;
const adapter = (_, __) => {
    if ((0, Utils_1.isTag)(_)) {
        return new GenSync((0, has_1.accessService)(_)(Function_1.identity));
    }
    if ((0, Utils_1.isEither)(_)) {
        return new GenSync(_._tag === "Left" ? (0, core_1.fail)(_.left) : (0, core_1.succeed)(_.right));
    }
    if ((0, Utils_1.isOption)(_)) {
        return new GenSync(_._tag === "None"
            ? (0, core_1.fail)(__ ? __() : new GlobalExceptions_1.NoSuchElementException())
            : (0, core_1.succeed)(_.value));
    }
    return new GenSync(_);
};
function gen(f) {
    return (0, core_1.suspend)(() => {
        const iterator = f(adapter);
        const state = iterator.next();
        function run(state) {
            if (state.done) {
                return (0, core_1.succeed)(state.value);
            }
            return (0, core_1.chain_)(state.value["effect"], (val) => {
                const next = iterator.next(val);
                return run(next);
            });
        }
        return run(state);
    });
}
exports.gen = gen;
//# sourceMappingURL=gen.js.map