/**
 * @fileoverview A class to manage state of generating a code path.
 * @author Toru Nagashima
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const CodePathSegment = require("./code-path-segment"),
    ForkContext = require("./fork-context");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * Adds given segments into the `dest` array.
 * If the `others` array does not includes the given segments, adds to the `all`
 * array as well.
 *
 * This adds only reachable and used segments.
 * @param {CodePathSegment[]} dest A destination array (`returnedSegments` or `thrownSegments`).
 * @param {CodePathSegment[]} others Another destination array (`returnedSegments` or `thrownSegments`).
 * @param {CodePathSegment[]} all The unified destination array (`finalSegments`).
 * @param {CodePathSegment[]} segments Segments to add.
 * @returns {void}
 */
function addToReturnedOrThrown(dest, others, all, segments) {
    for (let i = 0; i < segments.length; ++i) {
        const segment = segments[i];

        dest.push(segment);
        if (others.indexOf(segment) === -1) {
            all.push(segment);
        }
    }
}

/**
 * Gets a loop-context for a `continue` statement.
 * @param {CodePathState} state A state to get.
 * @param {string} label The label of a `continue` statement.
 * @returns {LoopContext} A loop-context for a `continue` statement.
 */
function getContinueContext(state, label) {
    if (!label) {
        return state.loopContext;
    }

    let context = state.loopContext;

    while (context) {
        if (context.label === label) {
            return context;
        }
        context = context.upper;
    }

    /* istanbul ignore next: foolproof (syntax error) */
    return null;
}

/**
 * Gets a context for a `break` statement.
 * @param {CodePathState} state A state to get.
 * @param {string} label The label of a `break` statement.
 * @returns {LoopContext|SwitchContext} A context for a `break` statement.
 */
function getBreakContext(state, label) {
    let context = state.breakContext;

    while (context) {
        if (label ? context.label === label : context.breakable) {
            return context;
        }
        context = context.upper;
    }

    /* istanbul ignore next: foolproof (syntax error) */
    return null;
}

/**
 * Gets a context for a `return` statement.
 * @param {CodePathState} state A state to get.
 * @returns {TryContext|CodePathState} A context for a `return` statement.
 */
function getReturnContext(state) {
    let context = state.tryContext;

    while (context) {
        if (context.hasFinalizer && context.position !== "finally") {
            return context;
        }
        context = context.upper;
    }

    return state;
}

/**
 * Gets a context for a `throw` statement.
 * @param {CodePathState} state A state to get.
 * @returns {TryContext|CodePathState} A context for a `throw` statement.
 */
function getThrowContext(state) {
    let context = state.tryContext;

    while (context) {
        if (context.position === "try" ||
            (context.hasFinalizer && context.position === "catch")
        ) {
            return context;
        }
        context = context.upper;
    }

    return state;
}

/**
 * Removes a given element from a given array.
 * @param {any[]} xs An array to remove the specific element.
 * @param {any} x An element to be removed.
 * @returns {void}
 */
function remove(xs, x) {
    xs.splice(xs.indexOf(x), 1);
}

/**
 * Disconnect given segments.
 *
 * This is used in a process for switch statements.
 * If there is the "default" chunk before other cases, the order is different
 * between node's and running's.
 * @param {CodePathSegment[]} prevSegments Forward segments to disconnect.
 * @param {CodePathSegment[]} nextSegments Backward segments to disconnect.
 * @returns {void}
 */
function removeConnection(prevSegments, nextSegments) {
    for (let i = 0; i < prevSegments.length; ++i) {
        const prevSegment = prevSegments[i];
        const nextSegment = nextSegments[i];

        remove(prevSegment.nextSegments, nextSegment);
        remove(prevSegment.allNextSegments, nextSegment);
        remove(nextSegment.prevSegments, prevSegment);
        remove(nextSegment.allPrevSegments, prevSegment);
    }
}

/**
 * Creates looping path.
 * @param {CodePathState} state The instance.
 * @param {CodePathSegment[]} unflattenedFromSegments Segments which are source.
 * @param {CodePathSegment[]} unflattenedToSegments Segments which are destination.
 * @returns {void}
 */
function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) {
    const fromSegments = CodePathSegment.flattenUnusedSegments(unflattenedFromSegments);
    const toSegments = CodePathSegment.flattenUnusedSegments(unflattenedToSegments);

    const end = Math.min(fromSegments.length, toSegments.length);

    for (let i = 0; i < end; ++i) {
        const fromSegment = fromSegments[i];
        const toSegment = toSegments[i];

        if (toSegment.reachable) {
            fromSegment.nextSegments.push(toSegment);
        }
        if (fromSegment.reachable) {
            toSegment.prevSegments.push(fromSegment);
        }
        fromSegment.allNextSegments.push(toSegment);
        toSegment.allPrevSegments.push(fromSegment);

        if (toSegment.allPrevSegments.length >= 2) {
            CodePathSegment.markPrevSegmentAsLooped(toSegment, fromSegment);
        }

        state.notifyLooped(fromSegment, toSegment);
    }
}

/**
 * Finalizes segments of `test` chunk of a ForStatement.
 *
 * - Adds `false` paths to paths which are leaving from the loop.
 * - Sets `true` paths to paths which go to the body.
 * @param {LoopContext} context A loop context to modify.
 * @param {ChoiceContext} choiceContext A choice context of this loop.
 * @param {CodePathSegment[]} head The current head paths.
 * @returns {void}
 */
function finalizeTestSegmentsOfFor(context, choiceContext, head) {
    if (!choiceContext.processed) {
        choiceContext.trueForkContext.add(head);
        choiceContext.falseForkContext.add(head);
        choiceContext.qqForkContext.add(head);
    }

    if (context.test !== true) {
        context.brokenForkContext.addAll(choiceContext.falseForkContext);
    }
    context.endOfTestSegments = choiceContext.trueForkContext.makeNext(0, -1);
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

/**
 * A class which manages state to analyze code paths.
 */
class CodePathState {

    /**
     * @param {IdGenerator} idGenerator An id generator to generate id for code
     *   path segments.
     * @param {Function} onLooped A callback function to notify looping.
     */
    constructor(idGenerator, onLooped) {
        this.idGenerator = idGenerator;
        this.notifyLooped = onLooped;
        this.forkContext = ForkContext.newRoot(idGenerator);
        this.choiceContext = null;
        this.switchContext = null;
        this.tryContext = null;
        this.loopContext = null;
        this.breakContext = null;
        this.chainContext = null;

        this.currentSegments = [];
        this.initialSegment = this.forkContext.head[0];

        // returnedSegments and thrownSegments push elements into finalSegments also.
        const final = this.finalSegments = [];
        const returned = this.returnedForkContext = [];
        const thrown = this.thrownForkContext = [];

        returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final);
        thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final);
    }

    /**
     * The head segments.
     * @type {CodePathSegment[]}
     */
    get headSegments() {
        return this.forkContext.head;
    }

    /**
     * The parent forking context.
     * This is used for the root of new forks.
     * @type {ForkContext}
     */
    get parentForkContext() {
        const current = this.forkContext;

        return current && current.upper;
    }

    /**
     * Creates and stacks new forking context.
     * @param {boolean} forkLeavingPath A flag which shows being in a
     *   "finally" block.
     * @returns {ForkContext} The created context.
     */
    pushForkContext(forkLeavingPath) {
        this.forkContext = ForkContext.newEmpty(
            this.forkContext,
            forkLeavingPath
        );

        return this.forkContext;
    }

    /**
     * Pops and merges the last forking context.
     * @returns {ForkContext} The last context.
     */
    popForkContext() {
        const lastContext = this.forkContext;

        this.forkContext = lastContext.upper;
        this.forkContext.replaceHead(lastContext.makeNext(0, -1));

        return lastContext;
    }

    /**
     * Creates a new path.
     * @returns {void}
     */
    forkPath() {
        this.forkContext.add(this.parentForkContext.makeNext(-1, -1));
    }

    /**
     * Creates a bypass path.
     * This is used for such as IfStatement which does not have "else" chunk.
     * @returns {void}
     */
    forkBypassPath() {
        this.forkContext.add(this.parentForkContext.head);
    }

    //--------------------------------------------------------------------------
    // ConditionalExpression, LogicalExpression, IfStatement
    //--------------------------------------------------------------------------

    /**
     * Creates a context for ConditionalExpression, LogicalExpression, AssignmentExpression (logical assignments only),
     * IfStatement, WhileStatement, DoWhileStatement, or ForStatement.
     *
     * LogicalExpressions have cases that it goes different paths between the
     * `true` case and the `false` case.
     *
     * For Example:
     *
     *     if (a || b) {
     *         foo();
     *     } else {
     *         bar();
     *     }
     *
     * In this case, `b` is evaluated always in the code path of the `else`
     * block, but it's not so in the code path of the `if` block.
     * So there are 3 paths.
     *
     *     a -> foo();
     *     a -> b -> foo();
     *     a -> b -> bar();
     * @param {string} kind A kind string.
     *   If the new context is LogicalExpression's or AssignmentExpression's, this is `"&&"` or `"||"` or `"??"`.
     *   If it's IfStatement's or ConditionalExpression's, this is `"test"`.
     *   Otherwise, this is `"loop"`.
     * @param {boolean} isForkingAsResult A flag that shows that goes different
     *   paths between `true` and `false`.
     * @returns {void}
     */
    pushChoiceContext(kind, isForkingAsResult) {
        this.choiceContext = {
            upper: this.choiceContext,
            kind,
            isForkingAsResult,
            trueForkContext: ForkContext.newEmpty(this.forkContext),
            falseForkContext: ForkContext.newEmpty(this.forkContext),
            qqForkContext: ForkContext.newEmpty(this.forkContext),
            processed: false
        };
    }

    /**
     * Pops the last choice context and finalizes it.
     * @throws {Error} (Unreachable.)
     * @returns {ChoiceContext} The popped context.
     */
    popChoiceContext() {
        const context = this.choiceContext;

        this.choiceContext = context.upper;

        const forkContext = this.forkContext;
        const headSegments = forkContext.head;

        switch (context.kind) {
            case "&&":
            case "||":
            case "??":

                /*
                 * If any result were not transferred from child contexts,
                 * this sets the head segments to both cases.
                 * The head segments are the path of the right-hand operand.
                 */
                if (!context.processed) {
                    context.trueForkContext.add(headSegments);
                    context.falseForkContext.add(headSegments);
                    context.qqForkContext.add(headSegments);
                }

                /*
                 * Transfers results to upper context if this context is in
                 * test chunk.
                 */
                if (context.isForkingAsResult) {
                    const parentContext = this.choiceContext;

                    parentContext.trueForkContext.addAll(context.trueForkContext);
                    parentContext.falseForkContext.addAll(context.falseForkContext);
                    parentContext.qqForkContext.addAll(context.qqForkContext);
                    parentContext.processed = true;

                    return context;
                }

                break;

            case "test":
                if (!context.processed) {

                    /*
                     * The head segments are the path of the `if` block here.
                     * Updates the `true` path with the end of the `if` block.
                     */
                    context.trueForkContext.clear();
                    context.trueForkContext.add(headSegments);
                } else {

                    /*
                     * The head segments are the path of the `else` block here.
                     * Updates the `false` path with the end of the `else`
                     * block.
                     */
                    context.falseForkContext.clear();
                    context.falseForkContext.add(headSegments);
                }

                break;

            case "loop":

                /*
                 * Loops are addressed in popLoopContext().
                 * This is called from popLoopContext().
                 */
                return context;

            /* istanbul ignore next */
            default:
                throw new Error("unreachable");
        }

        // Merges all paths.
        const prevForkContext = context.trueForkContext;

        prevForkContext.addAll(context.falseForkContext);
        forkContext.replaceHead(prevForkContext.makeNext(0, -1));

        return context;
    }

    /**
     * Makes a code path segment of the right-hand operand of a logical
     * expression.
     * @throws {Error} (Unreachable.)
     * @returns {void}
     */
    makeLogicalRight() {
        const context = this.choiceContext;
        const forkContext = this.forkContext;

        if (context.processed) {

            /*
             * This got segments already from the child choice context.
             * Creates the next path from own true/false fork context.
             */
            let prevForkContext;

            switch (context.kind) {
                case "&&": // if true then go to the right-hand side.
                    prevForkContext = context.trueForkContext;
                    break;
                case "||": // if false then go to the right-hand side.
                    prevForkContext = context.falseForkContext;
                    break;
                case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext.
                    prevForkContext = context.qqForkContext;
                    break;
                default:
                    throw new Error("unreachable");
            }

            forkContext.replaceHead(prevForkContext.makeNext(0, -1));
            prevForkContext.clear();
            context.processed = false;
        } else {

            /*
             * This did not get segments from the child choice context.
             * So addresses the head segments.
             * The head segments are the path of the left-hand operand.
             */
            switch (context.kind) {
                case "&&": // the false path can short-circuit.
                    context.falseForkContext.add(forkContext.head);
                    break;
                case "||": // the true path can short-circuit.
                    context.trueForkContext.add(forkContext.head);
                    break;
                case "??": // both can short-circuit.
                    context.trueForkContext.add(forkContext.head);
                    context.falseForkContext.add(forkContext.head);
                    break;
                default:
                    throw new Error("unreachable");
            }

            forkContext.replaceHead(forkContext.makeNext(-1, -1));
        }
    }

    /**
     * Makes a code path segment of the `if` block.
     * @returns {void}
     */
    makeIfConsequent() {
        const context = this.choiceContext;
        const forkContext = this.forkContext;

        /*
         * If any result were not transferred from child contexts,
         * this sets the head segments to both cases.
         * The head segments are the path of the test expression.
         */
        if (!context.processed) {
            context.trueForkContext.add(forkContext.head);
            context.falseForkContext.add(forkContext.head);
            context.qqForkContext.add(forkContext.head);
        }

        context.processed = false;

        // Creates new path from the `true` case.
        forkContext.replaceHead(
            context.trueForkContext.makeNext(0, -1)
        );
    }

    /**
     * Makes a code path segment of the `else` block.
     * @returns {void}
     */
    makeIfAlternate() {
        const context = this.choiceContext;
        const forkContext = this.forkContext;

        /*
         * The head segments are the path of the `if` block.
         * Updates the `true` path with the end of the `if` block.
         */
        context.trueForkContext.clear();
        context.trueForkContext.add(forkContext.head);
        context.processed = true;

        // Creates new path from the `false` case.
        forkContext.replaceHead(
            context.falseForkContext.makeNext(0, -1)
        );
    }

    //--------------------------------------------------------------------------
    // ChainExpression
    //--------------------------------------------------------------------------

    /**
     * Push a new `ChainExpression` context to the stack.
     * This method is called on entering to each `ChainExpression` node.
     * This context is used to count forking in the optional chain then merge them on the exiting from the `ChainExpression` node.
     * @returns {void}
     */
    pushChainContext() {
        this.chainContext = {
            upper: this.chainContext,
            countChoiceContexts: 0
        };
    }

    /**
     * Pop a `ChainExpression` context from the stack.
     * This method is called on exiting from each `ChainExpression` node.
     * This merges all forks of the last optional chaining.
     * @returns {void}
     */
    popChainContext() {
        const context = this.chainContext;

        this.chainContext = context.upper;

        // pop all choice contexts of this.
        for (let i = context.countChoiceContexts; i > 0; --i) {
            this.popChoiceContext();
        }
    }

    /**
     * Create a choice context for optional access.
     * This method is called on entering to each `(Call|Member)Expression[optional=true]` node.
     * This creates a choice context as similar to `LogicalExpression[operator="??"]` node.
     * @returns {void}
     */
    makeOptionalNode() {
        if (this.chainContext) {
            this.chainContext.countChoiceContexts += 1;
            this.pushChoiceContext("??", false);
        }
    }

    /**
     * Create a fork.
     * This method is called on entering to the `arguments|property` property of each `(Call|Member)Expression` node.
     * @returns {void}
     */
    makeOptionalRight() {
        if (this.chainContext) {
            this.makeLogicalRight();
        }
    }

    //--------------------------------------------------------------------------
    // SwitchStatement
    //--------------------------------------------------------------------------

    /**
     * Creates a context object of SwitchStatement and stacks it.
     * @param {boolean} hasCase `true` if the switch statement has one or more
     *   case parts.
     * @param {string|null} label The label text.
     * @returns {void}
     */
    pushSwitchContext(hasCase, label) {
        this.switchContext = {
            upper: this.switchContext,
            hasCase,
            defaultSegments: null,
            defaultBodySegments: null,
            foundDefault: false,
            lastIsDefault: false,
            countForks: 0
        };

        this.pushBreakContext(true, label);
    }

    /**
     * Pops the last context of SwitchStatement and finalizes it.
     *
     * - Disposes all forking stack for `case` and `default`.
     * - Creates the next code path segment from `context.brokenForkContext`.
     * - If the last `SwitchCase` node is not a `default` part, creates a path
     *   to the `default` body.
     * @returns {void}
     */
    popSwitchContext() {
        const context = this.switchContext;

        this.switchContext = context.upper;

        const forkContext = this.forkContext;
        const brokenForkContext = this.popBreakContext().brokenForkContext;

        if (context.countForks === 0) {

            /*
             * When there is only one `default` chunk and there is one or more
             * `break` statements, even if forks are nothing, it needs to merge
             * those.
             */
            if (!brokenForkContext.empty) {
                brokenForkContext.add(forkContext.makeNext(-1, -1));
                forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
            }

            return;
        }

        const lastSegments = forkContext.head;

        this.forkBypassPath();
        const lastCaseSegments = forkContext.head;

        /*
         * `brokenForkContext` is used to make the next segment.
         * It must add the last segment into `brokenForkContext`.
         */
        brokenForkContext.add(lastSegments);

        /*
         * A path which is failed in all case test should be connected to path
         * of `default` chunk.
         */
        if (!context.lastIsDefault) {
            if (context.defaultBodySegments) {

                /*
                 * Remove a link from `default` label to its chunk.
                 * It's false route.
                 */
                removeConnection(context.defaultSegments, context.defaultBodySegments);
                makeLooped(this, lastCaseSegments, context.defaultBodySegments);
            } else {

                /*
                 * It handles the last case body as broken if `default` chunk
                 * does not exist.
                 */
                brokenForkContext.add(lastCaseSegments);
            }
        }

        // Pops the segment context stack until the entry segment.
        for (let i = 0; i < context.countForks; ++i) {
            this.forkContext = this.forkContext.upper;
        }

        /*
         * Creates a path from all brokenForkContext paths.
         * This is a path after switch statement.
         */
        this.forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
    }

    /**
     * Makes a code path segment for a `SwitchCase` node.
     * @param {boolean} isEmpty `true` if the body is empty.
     * @param {boolean} isDefault `true` if the body is the default case.
     * @returns {void}
     */
    makeSwitchCaseBody(isEmpty, isDefault) {
        const context = this.switchContext;

        if (!context.hasCase) {
            return;
        }

        /*
         * Merge forks.
         * The parent fork context has two segments.
         * Those are from the current case and the body of the previous case.
         */
        const parentForkContext = this.forkContext;
        const forkContext = this.pushForkContext();

        forkContext.add(parentForkContext.makeNext(0, -1));

        /*
         * Save `default` chunk info.
         * If the `default` label is not at the last, we must make a path from
         * the last `case` to the `default` chunk.
         */
        if (isDefault) {
            context.defaultSegments = parentForkContext.head;
            if (isEmpty) {
                context.foundDefault = true;
            } else {
                context.defaultBodySegments = forkContext.head;
            }
        } else {
            if (!isEmpty && context.foundDefault) {
                context.foundDefault = false;
                context.defaultBodySegments = forkContext.head;
            }
        }

        context.lastIsDefault = isDefault;
        context.countForks += 1;
    }

    //--------------------------------------------------------------------------
    // TryStatement
    //--------------------------------------------------------------------------

    /**
     * Creates a context object of TryStatement and stacks it.
     * @param {boolean} hasFinalizer `true` if the try statement has a
     *   `finally` block.
     * @returns {void}
     */
    pushTryContext(hasFinalizer) {
        this.tryContext = {
            upper: this.tryContext,
            position: "try",
            hasFinalizer,

            returnedForkContext: hasFinalizer
                ? ForkContext.newEmpty(this.forkContext)
                : null,

            thrownForkContext: ForkContext.newEmpty(this.forkContext),
            lastOfTryIsReachable: false,
            lastOfCatchIsReachable: false
        };
    }

    /**
     * Pops the last context of TryStatement and finalizes it.
     * @returns {void}
     */
    popTryContext() {
        const context = this.tryContext;

        this.tryContext = context.upper;

        if (context.position === "catch") {

            // Merges two paths from the `try` block and `catch` block merely.
            this.popForkContext();
            return;
        }

        /*
         * The following process is executed only when there is the `finally`
         * block.
         */

        const returned = context.returnedForkContext;
        const thrown = context.thrownForkContext;

        if (returned.empty && thrown.empty) {
            return;
        }

        // Separate head to normal paths and leaving paths.
        const headSegments = this.forkContext.head;

        this.forkContext = this.forkContext.upper;
        const normalSegments = headSegments.slice(0, headSegments.length / 2 | 0);
        const leavingSegments = headSegments.slice(headSegments.length / 2 | 0);

        // Forwards the leaving path to upper contexts.
        if (!returned.empty) {
            getReturnContext(this).returnedForkContext.add(leavingSegments);
        }
        if (!thrown.empty) {
            getThrowContext(this).thrownForkContext.add(leavingSegments);
        }

        // Sets the normal path as the next.
        this.forkContext.replaceHead(normalSegments);

        /*
         * If both paths of the `try` block and the `catch` block are
         * unreachable, the next path becomes unreachable as well.
         */
        if (!context.lastOfTryIsReachable && !context.lastOfCatchIsReachable) {
            this.forkContext.makeUnreachable();
        }
    }

    /**
     * Makes a code path segment for a `catch` block.
     * @returns {void}
     */
    makeCatchBlock() {
        const context = this.tryContext;
        const forkContext = this.forkContext;
        const thrown = context.thrownForkContext;

        // Update state.
        context.position = "catch";
        context.thrownForkContext = ForkContext.newEmpty(forkContext);
        context.lastOfTryIsReachable = forkContext.reachable;

        // Merge thrown paths.
        thrown.add(forkContext.head);
        const thrownSegments = thrown.makeNext(0, -1);

        // Fork to a bypass and the merged thrown path.
        this.pushForkContext();
        this.forkBypassPath();
        this.forkContext.add(thrownSegments);
    }

    /**
     * Makes a code path segment for a `finally` block.
     *
     * In the `finally` block, parallel paths are created. The parallel paths
     * are used as leaving-paths. The leaving-paths are paths from `return`
     * statements and `throw` statements in a `try` block or a `catch` block.
     * @returns {void}
     */
    makeFinallyBlock() {
        const context = this.tryContext;
        let forkContext = this.forkContext;
        const returned = context.returnedForkContext;
        const thrown = context.thrownForkContext;
        const headOfLeavingSegments = forkContext.head;

        // Update state.
        if (context.position === "catch") {

            // Merges two paths from the `try` block and `catch` block.
            this.popForkContext();
            forkContext = this.forkContext;

            context.lastOfCatchIsReachable = forkContext.reachable;
        } else {
            context.lastOfTryIsReachable = forkContext.reachable;
        }
        context.position = "finally";

        if (returned.empty && thrown.empty) {

            // This path does not leave.
            return;
        }

        /*
         * Create a parallel segment from merging returned and thrown.
         * This segment will leave at the end of this finally block.
         */
        const segments = forkContext.makeNext(-1, -1);

        for (let i = 0; i < forkContext.count; ++i) {
            const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]];

            for (let j = 0; j < returned.segmentsList.length; ++j) {
                prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]);
            }
            for (let j = 0; j < thrown.segmentsList.length; ++j) {
                prevSegsOfLeavingSegment.push(thrown.segmentsList[j][i]);
            }

            segments.push(
                CodePathSegment.newNext(
                    this.idGenerator.next(),
                    prevSegsOfLeavingSegment
                )
            );
        }

        this.pushForkContext(true);
        this.forkContext.add(segments);
    }

    /**
     * Makes a code path segment from the first throwable node to the `catch`
     * block or the `finally` block.
     * @returns {void}
     */
    makeFirstThrowablePathInTryBlock() {
        const forkContext = this.forkContext;

        if (!forkContext.reachable) {
            return;
        }

        const context = getThrowContext(this);

        if (context === this ||
            context.position !== "try" ||
            !context.thrownForkContext.empty
        ) {
            return;
        }

        context.thrownForkContext.add(forkContext.head);
        forkContext.replaceHead(forkContext.makeNext(-1, -1));
    }

    //--------------------------------------------------------------------------
    // Loop Statements
    //--------------------------------------------------------------------------

    /**
     * Creates a context object of a loop statement and stacks it.
     * @param {string} type The type of the node which was triggered. One of
     *   `WhileStatement`, `DoWhileStatement`, `ForStatement`, `ForInStatement`,
     *   and `ForStatement`.
     * @param {string|null} label A label of the node which was triggered.
     * @throws {Error} (Unreachable - unknown type.)
     * @returns {void}
     */
    pushLoopContext(type, label) {
        const forkContext = this.forkContext;
        const breakContext = this.pushBreakContext(true, label);

        switch (type) {
            case "WhileStatement":
                this.pushChoiceContext("loop", false);
                this.loopContext = {
                    upper: this.loopContext,
                    type,
                    label,
                    test: void 0,
                    continueDestSegments: null,
                    brokenForkContext: breakContext.brokenForkContext
                };
                break;

            case "DoWhileStatement":
                this.pushChoiceContext("loop", false);
                this.loopContext = {
                    upper: this.loopContext,
                    type,
                    label,
                    test: void 0,
                    entrySegments: null,
                    continueForkContext: ForkContext.newEmpty(forkContext),
                    brokenForkContext: breakContext.brokenForkContext
                };
                break;

            case "ForStatement":
                this.pushChoiceContext("loop", false);
                this.loopContext = {
                    upper: this.loopContext,
                    type,
                    label,
                    test: void 0,
                    endOfInitSegments: null,
                    testSegments: null,
                    endOfTestSegments: null,
                    updateSegments: null,
                    endOfUpdateSegments: null,
                    continueDestSegments: null,
                    brokenForkContext: breakContext.brokenForkContext
                };
                break;

            case "ForInStatement":
            case "ForOfStatement":
                this.loopContext = {
                    upper: this.loopContext,
                    type,
                    label,
                    prevSegments: null,
                    leftSegments: null,
                    endOfLeftSegments: null,
                    continueDestSegments: null,
                    brokenForkContext: breakContext.brokenForkContext
                };
                break;

            /* istanbul ignore next */
            default:
                throw new Error(`unknown type: "${type}"`);
        }
    }

    /**
     * Pops the last context of a loop statement and finalizes it.
     * @throws {Error} (Unreachable - unknown type.)
     * @returns {void}
     */
    popLoopContext() {
        const context = this.loopContext;

        this.loopContext = context.upper;

        const forkContext = this.forkContext;
        const brokenForkContext = this.popBreakContext().brokenForkContext;

        // Creates a looped path.
        switch (context.type) {
            case "WhileStatement":
            case "ForStatement":
                this.popChoiceContext();
                makeLooped(
                    this,
                    forkContext.head,
                    context.continueDestSegments
                );
                break;

            case "DoWhileStatement": {
                const choiceContext = this.popChoiceContext();

                if (!choiceContext.processed) {
                    choiceContext.trueForkContext.add(forkContext.head);
                    choiceContext.falseForkContext.add(forkContext.head);
                }
                if (context.test !== true) {
                    brokenForkContext.addAll(choiceContext.falseForkContext);
                }

                // `true` paths go to looping.
                const segmentsList = choiceContext.trueForkContext.segmentsList;

                for (let i = 0; i < segmentsList.length; ++i) {
                    makeLooped(
                        this,
                        segmentsList[i],
                        context.entrySegments
                    );
                }
                break;
            }

            case "ForInStatement":
            case "ForOfStatement":
                brokenForkContext.add(forkContext.head);
                makeLooped(
                    this,
                    forkContext.head,
                    context.leftSegments
                );
                break;

            /* istanbul ignore next */
            default:
                throw new Error("unreachable");
        }

        // Go next.
        if (brokenForkContext.empty) {
            forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
        } else {
            forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
        }
    }

    /**
     * Makes a code path segment for the test part of a WhileStatement.
     * @param {boolean|undefined} test The test value (only when constant).
     * @returns {void}
     */
    makeWhileTest(test) {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const testSegments = forkContext.makeNext(0, -1);

        // Update state.
        context.test = test;
        context.continueDestSegments = testSegments;
        forkContext.replaceHead(testSegments);
    }

    /**
     * Makes a code path segment for the body part of a WhileStatement.
     * @returns {void}
     */
    makeWhileBody() {
        const context = this.loopContext;
        const choiceContext = this.choiceContext;
        const forkContext = this.forkContext;

        if (!choiceContext.processed) {
            choiceContext.trueForkContext.add(forkContext.head);
            choiceContext.falseForkContext.add(forkContext.head);
        }

        // Update state.
        if (context.test !== true) {
            context.brokenForkContext.addAll(choiceContext.falseForkContext);
        }
        forkContext.replaceHead(choiceContext.trueForkContext.makeNext(0, -1));
    }

    /**
     * Makes a code path segment for the body part of a DoWhileStatement.
     * @returns {void}
     */
    makeDoWhileBody() {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const bodySegments = forkContext.makeNext(-1, -1);

        // Update state.
        context.entrySegments = bodySegments;
        forkContext.replaceHead(bodySegments);
    }

    /**
     * Makes a code path segment for the test part of a DoWhileStatement.
     * @param {boolean|undefined} test The test value (only when constant).
     * @returns {void}
     */
    makeDoWhileTest(test) {
        const context = this.loopContext;
        const forkContext = this.forkContext;

        context.test = test;

        // Creates paths of `continue` statements.
        if (!context.continueForkContext.empty) {
            context.continueForkContext.add(forkContext.head);
            const testSegments = context.continueForkContext.makeNext(0, -1);

            forkContext.replaceHead(testSegments);
        }
    }

    /**
     * Makes a code path segment for the test part of a ForStatement.
     * @param {boolean|undefined} test The test value (only when constant).
     * @returns {void}
     */
    makeForTest(test) {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const endOfInitSegments = forkContext.head;
        const testSegments = forkContext.makeNext(-1, -1);

        // Update state.
        context.test = test;
        context.endOfInitSegments = endOfInitSegments;
        context.continueDestSegments = context.testSegments = testSegments;
        forkContext.replaceHead(testSegments);
    }

    /**
     * Makes a code path segment for the update part of a ForStatement.
     * @returns {void}
     */
    makeForUpdate() {
        const context = this.loopContext;
        const choiceContext = this.choiceContext;
        const forkContext = this.forkContext;

        // Make the next paths of the test.
        if (context.testSegments) {
            finalizeTestSegmentsOfFor(
                context,
                choiceContext,
                forkContext.head
            );
        } else {
            context.endOfInitSegments = forkContext.head;
        }

        // Update state.
        const updateSegments = forkContext.makeDisconnected(-1, -1);

        context.continueDestSegments = context.updateSegments = updateSegments;
        forkContext.replaceHead(updateSegments);
    }

    /**
     * Makes a code path segment for the body part of a ForStatement.
     * @returns {void}
     */
    makeForBody() {
        const context = this.loopContext;
        const choiceContext = this.choiceContext;
        const forkContext = this.forkContext;

        // Update state.
        if (context.updateSegments) {
            context.endOfUpdateSegments = forkContext.head;

            // `update` -> `test`
            if (context.testSegments) {
                makeLooped(
                    this,
                    context.endOfUpdateSegments,
                    context.testSegments
                );
            }
        } else if (context.testSegments) {
            finalizeTestSegmentsOfFor(
                context,
                choiceContext,
                forkContext.head
            );
        } else {
            context.endOfInitSegments = forkContext.head;
        }

        let bodySegments = context.endOfTestSegments;

        if (!bodySegments) {

            /*
             * If there is not the `test` part, the `body` path comes from the
             * `init` part and the `update` part.
             */
            const prevForkContext = ForkContext.newEmpty(forkContext);

            prevForkContext.add(context.endOfInitSegments);
            if (context.endOfUpdateSegments) {
                prevForkContext.add(context.endOfUpdateSegments);
            }

            bodySegments = prevForkContext.makeNext(0, -1);
        }
        context.continueDestSegments = context.continueDestSegments || bodySegments;
        forkContext.replaceHead(bodySegments);
    }

    /**
     * Makes a code path segment for the left part of a ForInStatement and a
     * ForOfStatement.
     * @returns {void}
     */
    makeForInOfLeft() {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const leftSegments = forkContext.makeDisconnected(-1, -1);

        // Update state.
        context.prevSegments = forkContext.head;
        context.leftSegments = context.continueDestSegments = leftSegments;
        forkContext.replaceHead(leftSegments);
    }

    /**
     * Makes a code path segment for the right part of a ForInStatement and a
     * ForOfStatement.
     * @returns {void}
     */
    makeForInOfRight() {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const temp = ForkContext.newEmpty(forkContext);

        temp.add(context.prevSegments);
        const rightSegments = temp.makeNext(-1, -1);

        // Update state.
        context.endOfLeftSegments = forkContext.head;
        forkContext.replaceHead(rightSegments);
    }

    /**
     * Makes a code path segment for the body part of a ForInStatement and a
     * ForOfStatement.
     * @returns {void}
     */
    makeForInOfBody() {
        const context = this.loopContext;
        const forkContext = this.forkContext;
        const temp = ForkContext.newEmpty(forkContext);

        temp.add(context.endOfLeftSegments);
        const bodySegments = temp.makeNext(-1, -1);

        // Make a path: `right` -> `left`.
        makeLooped(this, forkContext.head, context.leftSegments);

        // Update state.
        context.brokenForkContext.add(forkContext.head);
        forkContext.replaceHead(bodySegments);
    }

    //--------------------------------------------------------------------------
    // Control Statements
    //--------------------------------------------------------------------------

    /**
     * Creates new context for BreakStatement.
     * @param {boolean} breakable The flag to indicate it can break by
     *      an unlabeled BreakStatement.
     * @param {string|null} label The label of this context.
     * @returns {Object} The new context.
     */
    pushBreakContext(breakable, label) {
        this.breakContext = {
            upper: this.breakContext,
            breakable,
            label,
            brokenForkContext: ForkContext.newEmpty(this.forkContext)
        };
        return this.breakContext;
    }

    /**
     * Removes the top item of the break context stack.
     * @returns {Object} The removed context.
     */
    popBreakContext() {
        const context = this.breakContext;
        const forkContext = this.forkContext;

        this.breakContext = context.upper;

        // Process this context here for other than switches and loops.
        if (!context.breakable) {
            const brokenForkContext = context.brokenForkContext;

            if (!brokenForkContext.empty) {
                brokenForkContext.add(forkContext.head);
                forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
            }
        }

        return context;
    }

    /**
     * Makes a path for a `break` statement.
     *
     * It registers the head segment to a context of `break`.
     * It makes new unreachable segment, then it set the head with the segment.
     * @param {string} label A label of the break statement.
     * @returns {void}
     */
    makeBreak(label) {
        const forkContext = this.forkContext;

        if (!forkContext.reachable) {
            return;
        }

        const context = getBreakContext(this, label);

        /* istanbul ignore else: foolproof (syntax error) */
        if (context) {
            context.brokenForkContext.add(forkContext.head);
        }

        forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
    }

    /**
     * Makes a path for a `continue` statement.
     *
     * It makes a looping path.
     * It makes new unreachable segment, then it set the head with the segment.
     * @param {string} label A label of the continue statement.
     * @returns {void}
     */
    makeContinue(label) {
        const forkContext = this.forkContext;

        if (!forkContext.reachable) {
            return;
        }

        const context = getContinueContext(this, label);

        /* istanbul ignore else: foolproof (syntax error) */
        if (context) {
            if (context.continueDestSegments) {
                makeLooped(this, forkContext.head, context.continueDestSegments);

                // If the context is a for-in/of loop, this effects a break also.
                if (context.type === "ForInStatement" ||
                    context.type === "ForOfStatement"
                ) {
                    context.brokenForkContext.add(forkContext.head);
                }
            } else {
                context.continueForkContext.add(forkContext.head);
            }
        }
        forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
    }

    /**
     * Makes a path for a `return` statement.
     *
     * It registers the head segment to a context of `return`.
     * It makes new unreachable segment, then it set the head with the segment.
     * @returns {void}
     */
    makeReturn() {
        const forkContext = this.forkContext;

        if (forkContext.reachable) {
            getReturnContext(this).returnedForkContext.add(forkContext.head);
            forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
        }
    }

    /**
     * Makes a path for a `throw` statement.
     *
     * It registers the head segment to a context of `throw`.
     * It makes new unreachable segment, then it set the head with the segment.
     * @returns {void}
     */
    makeThrow() {
        const forkContext = this.forkContext;

        if (forkContext.reachable) {
            getThrowContext(this).thrownForkContext.add(forkContext.head);
            forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
        }
    }

    /**
     * Makes the final path.
     * @returns {void}
     */
    makeFinal() {
        const segments = this.currentSegments;

        if (segments.length > 0 && segments[0].reachable) {
            this.returnedForkContext.add(segments);
        }
    }
}

module.exports = CodePathState;
