/**
 * @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);
    }

    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.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,
     * 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, this is `"&&"` 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),
            processed: false
        };
    }

    /**
     * Pops the last choice context and finalizes it.
     *
     * @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 "||":

                /*
                 * 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);
                }

                /*
                 * 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.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.
     *
     * @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.
             */
            const prevForkContext =
                context.kind === "&&" ? context.trueForkContext
                /* kind === "||" */ : context.falseForkContext;

            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.
             */
            if (context.kind === "&&") {

                // The path does short-circuit if false.
                context.falseForkContext.add(forkContext.head);
            } else {

                // The path does short-circuit if true.
                context.trueForkContext.add(forkContext.head);
            }

            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.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)
        );
    }

    //--------------------------------------------------------------------------
    // 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.
     * @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.
     *
     * @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;
