"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CffStackMachine = void 0;
const errors_1 = require("@ot-builder/errors");
const variance_1 = require("@ot-builder/variance");
class CffStackMachine {
    constructor(ivs) {
        this.ivs = ivs;
        this.ivd = null;
        this.stack = [];
        this.vms = new variance_1.OtVar.MasterSet();
        if (ivs)
            this.ivd = ivs.tryGetIVD(0);
    }
    stackHeight() {
        return this.stack.length;
    }
    args(count) {
        if (this.stack.length < count) {
            throw errors_1.Errors.Cff.StackInsufficient(this.stack.length, count);
        }
        return this.stack.splice(this.stack.length - count, count);
    }
    allArgs(minCount = 0) {
        if (this.stack.length < minCount) {
            throw errors_1.Errors.Cff.StackInsufficient(this.stack.length, minCount);
        }
        const s1 = [...this.stack];
        this.stack.length = 0;
        return s1;
    }
    accumulate(vqs) {
        if (vqs.length < 2)
            return vqs;
        let s = vqs[0];
        for (let index = 1; index < vqs.length; index++) {
            s = variance_1.OtVar.Ops.add(s, vqs[index]);
            vqs[index] = s;
        }
        return vqs;
    }
    push(x) {
        this.stack.push(x);
    }
    pop() {
        return this.args(1)[0];
    }
    topIndex(n) {
        if (n >= this.stack.length)
            throw errors_1.Errors.Cff.StackInsufficient(this.stack.length, n);
        return this.stack[this.stack.length - n - 1];
    }
    reverseStack(left, right) {
        if (left < 0 || left >= this.stack.length || right < 0 || right >= this.stack.length) {
            throw errors_1.Errors.Cff.StackInsufficient(this.stack.length, left);
        }
        let p1 = left;
        let p2 = right;
        while (p1 < p2) {
            const temp = this.stack[p1];
            this.stack[p1] = this.stack[p2];
            this.stack[p2] = temp;
            p1++;
            p2--;
        }
    }
    setVsIndex(outId) {
        if (!this.ivs)
            throw errors_1.Errors.Cff.NotVariable();
        this.ivd = this.ivs.getIVD(outId);
    }
    doVsIndex() {
        const [_outId] = this.args(1);
        const outId = variance_1.OtVar.Ops.originOf(_outId);
        this.setVsIndex(outId);
        return outId;
    }
    doBlend() {
        if (!this.ivs || !this.ivd)
            throw errors_1.Errors.Cff.NotVariable();
        const [_n] = this.args(1);
        const nValues = variance_1.OtVar.Ops.originOf(_n);
        const nMasters = this.ivd.masterIDs.length;
        const args = this.args(nValues * (1 + nMasters));
        const results = [];
        for (let ixVal = 0; ixVal < nValues; ixVal++) {
            const orig = args[ixVal], variance = [];
            for (let ixMaster = 0; ixMaster < nMasters; ixMaster++) {
                variance[ixMaster] = variance_1.OtVar.Ops.originOf(args[nValues + ixVal * nMasters + ixMaster]);
            }
            results.push(variance_1.OtVar.Ops.add(orig, this.ivs.buildValue(this.ivd, variance)));
        }
        for (const x of results) {
            this.stack.push(x);
        }
    }
}
exports.CffStackMachine = CffStackMachine;
//# sourceMappingURL=stack-machine.js.map