/*
 * Copyright (C) 2020  Yomichan Authors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

const fs = require('fs');
const path = require('path');
const assert = require('assert');
const {testMain} = require('../dev/util');
const {VM} = require('../dev/vm');


function hasTermReasons(Deinflector, deinflector, source, expectedTerm, expectedRule, expectedReasons) {
    for (const {term, reasons, rules} of deinflector.deinflect(source, source)) {
        if (term !== expectedTerm) { continue; }
        if (typeof expectedRule !== 'undefined') {
            const expectedFlags = Deinflector.rulesToRuleFlags([expectedRule]);
            if (rules !== 0 && (rules & expectedFlags) !== expectedFlags) { continue; }
        }
        let okay = true;
        if (typeof expectedReasons !== 'undefined') {
            if (reasons.length !== expectedReasons.length) { continue; }
            for (let i = 0, ii = expectedReasons.length; i < ii; ++i) {
                if (expectedReasons[i] !== reasons[i]) {
                    okay = false;
                    break;
                }
            }
        }
        if (okay) {
            return {has: true, reasons, rules};
        }
    }
    return {has: false, reasons: null, rules: null};
}


function testDeinflections() {
    const data = [
        {
            valid: true,
            tests: [
                // Adjective
                {term: '愛しい', source: '愛しい',                 rule: 'adj-i', reasons: []},
                {term: '愛しい', source: '愛しそう',               rule: 'adj-i', reasons: ['-sou']},
                {term: '愛しい', source: '愛しすぎる',             rule: 'adj-i', reasons: ['-sugiru']},
                {term: '愛しい', source: '愛しかったら',           rule: 'adj-i', reasons: ['-tara']},
                {term: '愛しい', source: '愛しかったり',           rule: 'adj-i', reasons: ['-tari']},
                {term: '愛しい', source: '愛しくて',               rule: 'adj-i', reasons: ['-te']},
                {term: '愛しい', source: '愛しく',                 rule: 'adj-i', reasons: ['adv']},
                {term: '愛しい', source: '愛しくない',             rule: 'adj-i', reasons: ['negative']},
                {term: '愛しい', source: '愛しさ',                 rule: 'adj-i', reasons: ['noun']},
                {term: '愛しい', source: '愛しかった',             rule: 'adj-i', reasons: ['past']},
                {term: '愛しい', source: '愛しくありません',       rule: 'adj-i', reasons: ['polite negative']},
                {term: '愛しい', source: '愛しくありませんでした', rule: 'adj-i', reasons: ['polite past negative']},
                {term: '愛しい', source: '愛しき',                 rule: 'adj-i', reasons: ['-ki']},

                // Common verbs
                {term: '食べる', source: '食べる',           rule: 'v1', reasons: []},
                {term: '食べる', source: '食べます',         rule: 'v1', reasons: ['polite']},
                {term: '食べる', source: '食べた',           rule: 'v1', reasons: ['past']},
                {term: '食べる', source: '食べました',       rule: 'v1', reasons: ['polite past']},
                {term: '食べる', source: '食べて',           rule: 'v1', reasons: ['-te']},
                {term: '食べる', source: '食べられる',       rule: 'v1', reasons: ['potential or passive']},
                {term: '食べる', source: '食べられる',       rule: 'v1', reasons: ['potential or passive']},
                {term: '食べる', source: '食べさせる',       rule: 'v1', reasons: ['causative']},
                {term: '食べる', source: '食べさせられる',   rule: 'v1', reasons: ['causative', 'potential or passive']},
                {term: '食べる', source: '食べろ',           rule: 'v1', reasons: ['imperative']},
                {term: '食べる', source: '食べない',         rule: 'v1', reasons: ['negative']},
                {term: '食べる', source: '食べません',       rule: 'v1', reasons: ['polite negative']},
                {term: '食べる', source: '食べなかった',     rule: 'v1', reasons: ['negative', 'past']},
                {term: '食べる', source: '食べませんでした', rule: 'v1', reasons: ['polite past negative']},
                {term: '食べる', source: '食べなくて',       rule: 'v1', reasons: ['negative', '-te']},
                {term: '食べる', source: '食べられない',     rule: 'v1', reasons: ['potential or passive', 'negative']},
                {term: '食べる', source: '食べられない',     rule: 'v1', reasons: ['potential or passive', 'negative']},
                {term: '食べる', source: '食べさせない',     rule: 'v1', reasons: ['causative', 'negative']},
                {term: '食べる', source: '食べさせられない', rule: 'v1', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '食べる', source: '食べるな',         rule: 'v1', reasons: ['imperative negative']},

                {term: '食べる', source: '食べれば',         rule: 'v1', reasons: ['-ba']},
                {term: '食べる', source: '食べちゃう',       rule: 'v1', reasons: ['-chau']},
                {term: '食べる', source: '食べなさい',       rule: 'v1', reasons: ['-nasai']},
                {term: '食べる', source: '食べそう',         rule: 'v1', reasons: ['-sou']},
                {term: '食べる', source: '食べすぎる',       rule: 'v1', reasons: ['-sugiru']},
                {term: '食べる', source: '食べたい',         rule: 'v1', reasons: ['-tai']},
                {term: '食べる', source: '食べたら',         rule: 'v1', reasons: ['-tara']},
                {term: '食べる', source: '食べたり',         rule: 'v1', reasons: ['-tari']},
                {term: '食べる', source: '食べず',           rule: 'v1', reasons: ['-zu']},
                {term: '食べる', source: '食べぬ',           rule: 'v1', reasons: ['-nu']},
                {term: '食べる', source: '食べ',             rule: 'v1', reasons: ['masu stem']},
                {term: '食べる', source: '食べましょう',     rule: 'v1', reasons: ['polite volitional']},
                {term: '食べる', source: '食べよう',         rule: 'v1', reasons: ['volitional']},
                // ['causative passive']
                {term: '食べる', source: '食べとく',         rule: 'v1', reasons: ['-toku']},
                {term: '食べる', source: '食べている',       rule: 'v1', reasons: ['-te', 'progressive or perfect']},
                {term: '食べる', source: '食べておる',       rule: 'v1', reasons: ['-te', 'progressive or perfect']},
                {term: '食べる', source: '食べてる',         rule: 'v1', reasons: ['-te', 'progressive or perfect']},
                {term: '食べる', source: '食べとる',         rule: 'v1', reasons: ['-te', 'progressive or perfect']},

                {term: '買う', source: '買う',             rule: 'v5', reasons: []},
                {term: '買う', source: '買います',         rule: 'v5', reasons: ['polite']},
                {term: '買う', source: '買った',           rule: 'v5', reasons: ['past']},
                {term: '買う', source: '買いました',       rule: 'v5', reasons: ['polite past']},
                {term: '買う', source: '買って',           rule: 'v5', reasons: ['-te']},
                {term: '買う', source: '買える',           rule: 'v5', reasons: ['potential']},
                {term: '買う', source: '買われる',         rule: 'v5', reasons: ['passive']},
                {term: '買う', source: '買わせる',         rule: 'v5', reasons: ['causative']},
                {term: '買う', source: '買わせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '買う', source: '買え',             rule: 'v5', reasons: ['imperative']},
                {term: '買う', source: '買わない',         rule: 'v5', reasons: ['negative']},
                {term: '買う', source: '買いません',       rule: 'v5', reasons: ['polite negative']},
                {term: '買う', source: '買わなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '買う', source: '買いませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '買う', source: '買わなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '買う', source: '買えない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '買う', source: '買われない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '買う', source: '買わせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '買う', source: '買わせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '買う', source: '買うな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '買う', source: '買えば',           rule: 'v5', reasons: ['-ba']},
                {term: '買う', source: '買っちゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '買う', source: '買いなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '買う', source: '買いそう',         rule: 'v5', reasons: ['-sou']},
                {term: '買う', source: '買いすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '買う', source: '買いたい',         rule: 'v5', reasons: ['-tai']},
                {term: '買う', source: '買ったら',         rule: 'v5', reasons: ['-tara']},
                {term: '買う', source: '買ったり',         rule: 'v5', reasons: ['-tari']},
                {term: '買う', source: '買わず',           rule: 'v5', reasons: ['-zu']},
                {term: '買う', source: '買わぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '買う', source: '買い',             rule: 'v5', reasons: ['masu stem']},
                {term: '買う', source: '買いましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '買う', source: '買おう',           rule: 'v5', reasons: ['volitional']},
                {term: '買う', source: '買わされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '買う', source: '買っとく',         rule: 'v5', reasons: ['-toku']},
                {term: '買う', source: '買っている',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '買う', source: '買っておる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '買う', source: '買ってる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '買う', source: '買っとる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '行く', source: '行く',             rule: 'v5', reasons: []},
                {term: '行く', source: '行きます',         rule: 'v5', reasons: ['polite']},
                {term: '行く', source: '行った',           rule: 'v5', reasons: ['past']},
                {term: '行く', source: '行きました',       rule: 'v5', reasons: ['polite past']},
                {term: '行く', source: '行って',           rule: 'v5', reasons: ['-te']},
                {term: '行く', source: '行ける',           rule: 'v5', reasons: ['potential']},
                {term: '行く', source: '行かれる',         rule: 'v5', reasons: ['passive']},
                {term: '行く', source: '行かせる',         rule: 'v5', reasons: ['causative']},
                {term: '行く', source: '行かせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '行く', source: '行け',             rule: 'v5', reasons: ['imperative']},
                {term: '行く', source: '行かない',         rule: 'v5', reasons: ['negative']},
                {term: '行く', source: '行きません',       rule: 'v5', reasons: ['polite negative']},
                {term: '行く', source: '行かなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '行く', source: '行きませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '行く', source: '行かなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '行く', source: '行けない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '行く', source: '行かれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '行く', source: '行かせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '行く', source: '行かせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '行く', source: '行くな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '行く', source: '行けば',           rule: 'v5', reasons: ['-ba']},
                {term: '行く', source: '行っちゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '行く', source: '行きなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '行く', source: '行きそう',         rule: 'v5', reasons: ['-sou']},
                {term: '行く', source: '行きすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '行く', source: '行きたい',         rule: 'v5', reasons: ['-tai']},
                {term: '行く', source: '行いたら',         rule: 'v5', reasons: ['-tara']},
                {term: '行く', source: '行いたり',         rule: 'v5', reasons: ['-tari']},
                {term: '行く', source: '行かず',           rule: 'v5', reasons: ['-zu']},
                {term: '行く', source: '行かぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '行く', source: '行き',             rule: 'v5', reasons: ['masu stem']},
                {term: '行く', source: '行きましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '行く', source: '行こう',           rule: 'v5', reasons: ['volitional']},
                {term: '行く', source: '行かされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '行く', source: '行いとく',         rule: 'v5', reasons: ['-toku']},
                {term: '行く', source: '行っている',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '行く', source: '行っておる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '行く', source: '行ってる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '行く', source: '行っとる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '泳ぐ', source: '泳ぐ',             rule: 'v5', reasons: []},
                {term: '泳ぐ', source: '泳ぎます',         rule: 'v5', reasons: ['polite']},
                {term: '泳ぐ', source: '泳いだ',           rule: 'v5', reasons: ['past']},
                {term: '泳ぐ', source: '泳ぎました',       rule: 'v5', reasons: ['polite past']},
                {term: '泳ぐ', source: '泳いで',           rule: 'v5', reasons: ['-te']},
                {term: '泳ぐ', source: '泳げる',           rule: 'v5', reasons: ['potential']},
                {term: '泳ぐ', source: '泳がれる',         rule: 'v5', reasons: ['passive']},
                {term: '泳ぐ', source: '泳がせる',         rule: 'v5', reasons: ['causative']},
                {term: '泳ぐ', source: '泳がせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '泳ぐ', source: '泳げ',             rule: 'v5', reasons: ['imperative']},
                {term: '泳ぐ', source: '泳がない',         rule: 'v5', reasons: ['negative']},
                {term: '泳ぐ', source: '泳ぎません',       rule: 'v5', reasons: ['polite negative']},
                {term: '泳ぐ', source: '泳がなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '泳ぐ', source: '泳ぎませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '泳ぐ', source: '泳がなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '泳ぐ', source: '泳げない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '泳ぐ', source: '泳がれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '泳ぐ', source: '泳がせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '泳ぐ', source: '泳がせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '泳ぐ', source: '泳ぐな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '泳ぐ', source: '泳げば',           rule: 'v5', reasons: ['-ba']},
                {term: '泳ぐ', source: '泳いじゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '泳ぐ', source: '泳ぎなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '泳ぐ', source: '泳ぎそう',         rule: 'v5', reasons: ['-sou']},
                {term: '泳ぐ', source: '泳ぎすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '泳ぐ', source: '泳ぎたい',         rule: 'v5', reasons: ['-tai']},
                {term: '泳ぐ', source: '泳いだら',         rule: 'v5', reasons: ['-tara']},
                {term: '泳ぐ', source: '泳いだり',         rule: 'v5', reasons: ['-tari']},
                {term: '泳ぐ', source: '泳がず',           rule: 'v5', reasons: ['-zu']},
                {term: '泳ぐ', source: '泳がぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '泳ぐ', source: '泳ぎ',             rule: 'v5', reasons: ['masu stem']},
                {term: '泳ぐ', source: '泳ぎましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '泳ぐ', source: '泳ごう',           rule: 'v5', reasons: ['volitional']},
                {term: '泳ぐ', source: '泳がされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '泳ぐ', source: '泳いどく',         rule: 'v5', reasons: ['-toku']},
                {term: '泳ぐ', source: '泳いでいる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '泳ぐ', source: '泳いでおる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '泳ぐ', source: '泳いでる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '話す', source: '話す',             rule: 'v5', reasons: []},
                {term: '話す', source: '話します',         rule: 'v5', reasons: ['polite']},
                {term: '話す', source: '話した',           rule: 'v5', reasons: ['past']},
                {term: '話す', source: '話しました',       rule: 'v5', reasons: ['polite past']},
                {term: '話す', source: '話して',           rule: 'v5', reasons: ['-te']},
                {term: '話す', source: '話せる',           rule: 'v5', reasons: ['potential']},
                {term: '話す', source: '話される',         rule: 'v5', reasons: ['passive']},
                {term: '話す', source: '話させる',         rule: 'v5', reasons: ['causative']},
                {term: '話す', source: '話させられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '話す', source: '話せ',             rule: 'v5', reasons: ['imperative']},
                {term: '話す', source: '話さない',         rule: 'v5', reasons: ['negative']},
                {term: '話す', source: '話しません',       rule: 'v5', reasons: ['polite negative']},
                {term: '話す', source: '話さなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '話す', source: '話しませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '話す', source: '話さなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '話す', source: '話せない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '話す', source: '話されない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '話す', source: '話させない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '話す', source: '話させられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '話す', source: '話すな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '話す', source: '話せば',           rule: 'v5', reasons: ['-ba']},
                {term: '話す', source: '話しちゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '話す', source: '話しなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '話す', source: '話しそう',         rule: 'v5', reasons: ['-sou']},
                {term: '話す', source: '話しすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '話す', source: '話したい',         rule: 'v5', reasons: ['-tai']},
                {term: '話す', source: '話したら',         rule: 'v5', reasons: ['-tara']},
                {term: '話す', source: '話したり',         rule: 'v5', reasons: ['-tari']},
                {term: '話す', source: '話さず',           rule: 'v5', reasons: ['-zu']},
                {term: '話す', source: '話さぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '話す', source: '話し',             rule: 'v5', reasons: ['masu stem']},
                {term: '話す', source: '話しましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '話す', source: '話そう',           rule: 'v5', reasons: ['volitional']},
                // ['causative passive']
                {term: '話す', source: '話しとく',         rule: 'v5', reasons: ['-toku']},
                {term: '話す', source: '話している',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '話す', source: '話しておる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '話す', source: '話してる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '話す', source: '話しとる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '待つ', source: '待つ',             rule: 'v5', reasons: []},
                {term: '待つ', source: '待ちます',         rule: 'v5', reasons: ['polite']},
                {term: '待つ', source: '待った',           rule: 'v5', reasons: ['past']},
                {term: '待つ', source: '待ちました',       rule: 'v5', reasons: ['polite past']},
                {term: '待つ', source: '待って',           rule: 'v5', reasons: ['-te']},
                {term: '待つ', source: '待てる',           rule: 'v5', reasons: ['potential']},
                {term: '待つ', source: '待たれる',         rule: 'v5', reasons: ['passive']},
                {term: '待つ', source: '待たせる',         rule: 'v5', reasons: ['causative']},
                {term: '待つ', source: '待たせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '待つ', source: '待て',             rule: 'v5', reasons: ['imperative']},
                {term: '待つ', source: '待たない',         rule: 'v5', reasons: ['negative']},
                {term: '待つ', source: '待ちません',       rule: 'v5', reasons: ['polite negative']},
                {term: '待つ', source: '待たなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '待つ', source: '待ちませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '待つ', source: '待たなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '待つ', source: '待てない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '待つ', source: '待たれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '待つ', source: '待たせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '待つ', source: '待たせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '待つ', source: '待つな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '待つ', source: '待てば',           rule: 'v5', reasons: ['-ba']},
                {term: '待つ', source: '待っちゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '待つ', source: '待ちなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '待つ', source: '待ちそう',         rule: 'v5', reasons: ['-sou']},
                {term: '待つ', source: '待ちすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '待つ', source: '待ちたい',         rule: 'v5', reasons: ['-tai']},
                {term: '待つ', source: '待ったら',         rule: 'v5', reasons: ['-tara']},
                {term: '待つ', source: '待ったり',         rule: 'v5', reasons: ['-tari']},
                {term: '待つ', source: '待たず',           rule: 'v5', reasons: ['-zu']},
                {term: '待つ', source: '待たぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '待つ', source: '待ち',             rule: 'v5', reasons: ['masu stem']},
                {term: '待つ', source: '待ちましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '待つ', source: '待とう',           rule: 'v5', reasons: ['volitional']},
                {term: '待つ', source: '待たされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '待つ', source: '待っとく',         rule: 'v5', reasons: ['-toku']},
                {term: '待つ', source: '待っている',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '待つ', source: '待っておる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '待つ', source: '待ってる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '待つ', source: '待っとる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '死ぬ', source: '死ぬ',             rule: 'v5', reasons: []},
                {term: '死ぬ', source: '死にます',         rule: 'v5', reasons: ['polite']},
                {term: '死ぬ', source: '死んだ',           rule: 'v5', reasons: ['past']},
                {term: '死ぬ', source: '死にました',       rule: 'v5', reasons: ['polite past']},
                {term: '死ぬ', source: '死んで',           rule: 'v5', reasons: ['-te']},
                {term: '死ぬ', source: '死ねる',           rule: 'v5', reasons: ['potential']},
                {term: '死ぬ', source: '死なれる',         rule: 'v5', reasons: ['passive']},
                {term: '死ぬ', source: '死なせる',         rule: 'v5', reasons: ['causative']},
                {term: '死ぬ', source: '死なせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '死ぬ', source: '死ね',             rule: 'v5', reasons: ['imperative']},
                {term: '死ぬ', source: '死なない',         rule: 'v5', reasons: ['negative']},
                {term: '死ぬ', source: '死にません',       rule: 'v5', reasons: ['polite negative']},
                {term: '死ぬ', source: '死ななかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '死ぬ', source: '死にませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '死ぬ', source: '死ななくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '死ぬ', source: '死ねない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '死ぬ', source: '死なれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '死ぬ', source: '死なせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '死ぬ', source: '死なせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '死ぬ', source: '死ぬな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '死ぬ', source: '死ねば',           rule: 'v5', reasons: ['-ba']},
                {term: '死ぬ', source: '死んじゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '死ぬ', source: '死になさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '死ぬ', source: '死にそう',         rule: 'v5', reasons: ['-sou']},
                {term: '死ぬ', source: '死にすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '死ぬ', source: '死にたい',         rule: 'v5', reasons: ['-tai']},
                {term: '死ぬ', source: '死んだら',         rule: 'v5', reasons: ['-tara']},
                {term: '死ぬ', source: '死んだり',         rule: 'v5', reasons: ['-tari']},
                {term: '死ぬ', source: '死なず',           rule: 'v5', reasons: ['-zu']},
                {term: '死ぬ', source: '死なぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '死ぬ', source: '死に',             rule: 'v5', reasons: ['masu stem']},
                {term: '死ぬ', source: '死にましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '死ぬ', source: '死のう',           rule: 'v5', reasons: ['volitional']},
                {term: '死ぬ', source: '死なされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '死ぬ', source: '死んどく',         rule: 'v5', reasons: ['-toku']},
                {term: '死ぬ', source: '死んでいる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '死ぬ', source: '死んでおる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '死ぬ', source: '死んでる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '遊ぶ', source: '遊ぶ',             rule: 'v5', reasons: []},
                {term: '遊ぶ', source: '遊びます',         rule: 'v5', reasons: ['polite']},
                {term: '遊ぶ', source: '遊んだ',           rule: 'v5', reasons: ['past']},
                {term: '遊ぶ', source: '遊びました',       rule: 'v5', reasons: ['polite past']},
                {term: '遊ぶ', source: '遊んで',           rule: 'v5', reasons: ['-te']},
                {term: '遊ぶ', source: '遊べる',           rule: 'v5', reasons: ['potential']},
                {term: '遊ぶ', source: '遊ばれる',         rule: 'v5', reasons: ['passive']},
                {term: '遊ぶ', source: '遊ばせる',         rule: 'v5', reasons: ['causative']},
                {term: '遊ぶ', source: '遊ばせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '遊ぶ', source: '遊べ',             rule: 'v5', reasons: ['imperative']},
                {term: '遊ぶ', source: '遊ばない',         rule: 'v5', reasons: ['negative']},
                {term: '遊ぶ', source: '遊びません',       rule: 'v5', reasons: ['polite negative']},
                {term: '遊ぶ', source: '遊ばなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '遊ぶ', source: '遊びませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '遊ぶ', source: '遊ばなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '遊ぶ', source: '遊べない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '遊ぶ', source: '遊ばれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '遊ぶ', source: '遊ばせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '遊ぶ', source: '遊ばせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '遊ぶ', source: '遊ぶな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '遊ぶ', source: '遊べば',           rule: 'v5', reasons: ['-ba']},
                {term: '遊ぶ', source: '遊んじゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '遊ぶ', source: '遊びなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '遊ぶ', source: '遊びそう',         rule: 'v5', reasons: ['-sou']},
                {term: '遊ぶ', source: '遊びすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '遊ぶ', source: '遊びたい',         rule: 'v5', reasons: ['-tai']},
                {term: '遊ぶ', source: '遊んだら',         rule: 'v5', reasons: ['-tara']},
                {term: '遊ぶ', source: '遊んだり',         rule: 'v5', reasons: ['-tari']},
                {term: '遊ぶ', source: '遊ばず',           rule: 'v5', reasons: ['-zu']},
                {term: '遊ぶ', source: '遊ばぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '遊ぶ', source: '遊び',             rule: 'v5', reasons: ['masu stem']},
                {term: '遊ぶ', source: '遊びましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '遊ぶ', source: '遊ぼう',           rule: 'v5', reasons: ['volitional']},
                {term: '遊ぶ', source: '遊ばされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '遊ぶ', source: '遊んどく',         rule: 'v5', reasons: ['-toku']},
                {term: '遊ぶ', source: '遊んでいる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '遊ぶ', source: '遊んでおる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '遊ぶ', source: '遊んでる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '飲む', source: '飲む',             rule: 'v5', reasons: []},
                {term: '飲む', source: '飲みます',         rule: 'v5', reasons: ['polite']},
                {term: '飲む', source: '飲んだ',           rule: 'v5', reasons: ['past']},
                {term: '飲む', source: '飲みました',       rule: 'v5', reasons: ['polite past']},
                {term: '飲む', source: '飲んで',           rule: 'v5', reasons: ['-te']},
                {term: '飲む', source: '飲める',           rule: 'v5', reasons: ['potential']},
                {term: '飲む', source: '飲まれる',         rule: 'v5', reasons: ['passive']},
                {term: '飲む', source: '飲ませる',         rule: 'v5', reasons: ['causative']},
                {term: '飲む', source: '飲ませられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '飲む', source: '飲め',             rule: 'v5', reasons: ['imperative']},
                {term: '飲む', source: '飲まない',         rule: 'v5', reasons: ['negative']},
                {term: '飲む', source: '飲みません',       rule: 'v5', reasons: ['polite negative']},
                {term: '飲む', source: '飲まなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '飲む', source: '飲みませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '飲む', source: '飲まなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '飲む', source: '飲めない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '飲む', source: '飲まれない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '飲む', source: '飲ませない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '飲む', source: '飲ませられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '飲む', source: '飲むな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '飲む', source: '飲めば',           rule: 'v5', reasons: ['-ba']},
                {term: '飲む', source: '飲んじゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '飲む', source: '飲みなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '飲む', source: '飲みそう',         rule: 'v5', reasons: ['-sou']},
                {term: '飲む', source: '飲みすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '飲む', source: '飲みたい',         rule: 'v5', reasons: ['-tai']},
                {term: '飲む', source: '飲んだら',         rule: 'v5', reasons: ['-tara']},
                {term: '飲む', source: '飲んだり',         rule: 'v5', reasons: ['-tari']},
                {term: '飲む', source: '飲まず',           rule: 'v5', reasons: ['-zu']},
                {term: '飲む', source: '飲まぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '飲む', source: '飲み',             rule: 'v5', reasons: ['masu stem']},
                {term: '飲む', source: '飲みましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '飲む', source: '飲もう',           rule: 'v5', reasons: ['volitional']},
                {term: '飲む', source: '飲まされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '飲む', source: '飲んどく',         rule: 'v5', reasons: ['-toku']},
                {term: '飲む', source: '飲んでいる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '飲む', source: '飲んでおる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '飲む', source: '飲んでる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                {term: '作る', source: '作る',             rule: 'v5', reasons: []},
                {term: '作る', source: '作ります',         rule: 'v5', reasons: ['polite']},
                {term: '作る', source: '作った',           rule: 'v5', reasons: ['past']},
                {term: '作る', source: '作りました',       rule: 'v5', reasons: ['polite past']},
                {term: '作る', source: '作って',           rule: 'v5', reasons: ['-te']},
                {term: '作る', source: '作れる',           rule: 'v5', reasons: ['potential']},
                {term: '作る', source: '作られる',         rule: 'v5', reasons: ['passive']},
                {term: '作る', source: '作らせる',         rule: 'v5', reasons: ['causative']},
                {term: '作る', source: '作らせられる',     rule: 'v5', reasons: ['causative', 'potential or passive']},
                {term: '作る', source: '作れ',             rule: 'v5', reasons: ['imperative']},
                {term: '作る', source: '作らない',         rule: 'v5', reasons: ['negative']},
                {term: '作る', source: '作りません',       rule: 'v5', reasons: ['polite negative']},
                {term: '作る', source: '作らなかった',     rule: 'v5', reasons: ['negative', 'past']},
                {term: '作る', source: '作りませんでした', rule: 'v5', reasons: ['polite past negative']},
                {term: '作る', source: '作らなくて',       rule: 'v5', reasons: ['negative', '-te']},
                {term: '作る', source: '作れない',         rule: 'v5', reasons: ['potential', 'negative']},
                {term: '作る', source: '作られない',       rule: 'v5', reasons: ['passive', 'negative']},
                {term: '作る', source: '作らせない',       rule: 'v5', reasons: ['causative', 'negative']},
                {term: '作る', source: '作らせられない',   rule: 'v5', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '作る', source: '作るな',           rule: 'v5', reasons: ['imperative negative']},

                {term: '作る', source: '作れば',           rule: 'v5', reasons: ['-ba']},
                {term: '作る', source: '作っちゃう',       rule: 'v5', reasons: ['-chau']},
                {term: '作る', source: '作りなさい',       rule: 'v5', reasons: ['-nasai']},
                {term: '作る', source: '作りそう',         rule: 'v5', reasons: ['-sou']},
                {term: '作る', source: '作りすぎる',       rule: 'v5', reasons: ['-sugiru']},
                {term: '作る', source: '作りたい',         rule: 'v5', reasons: ['-tai']},
                {term: '作る', source: '作ったら',         rule: 'v5', reasons: ['-tara']},
                {term: '作る', source: '作ったり',         rule: 'v5', reasons: ['-tari']},
                {term: '作る', source: '作らず',           rule: 'v5', reasons: ['-zu']},
                {term: '作る', source: '作らぬ',           rule: 'v5', reasons: ['-nu']},
                {term: '作る', source: '作り',             rule: 'v5', reasons: ['masu stem']},
                {term: '作る', source: '作りましょう',     rule: 'v5', reasons: ['polite volitional']},
                {term: '作る', source: '作ろう',           rule: 'v5', reasons: ['volitional']},
                {term: '作る', source: '作らされる',       rule: 'v5', reasons: ['causative passive']},
                {term: '作る', source: '作っとく',         rule: 'v5', reasons: ['-toku']},
                {term: '作る', source: '作っている',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '作る', source: '作っておる',       rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '作る', source: '作ってる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},
                {term: '作る', source: '作っとる',         rule: 'v5', reasons: ['-te', 'progressive or perfect']},

                // Irregular verbs
                {term: '為る', source: '為る',           rule: 'vs', reasons: []},
                {term: '為る', source: '為ます',         rule: 'vs', reasons: ['polite']},
                {term: '為る', source: '為た',           rule: 'vs', reasons: ['past']},
                {term: '為る', source: '為ました',       rule: 'vs', reasons: ['polite past']},
                {term: '為る', source: '為て',           rule: 'vs', reasons: ['-te']},
                {term: '為る', source: '為られる',       rule: 'vs', reasons: ['potential or passive']},
                {term: '為る', source: '為れる',         rule: 'vs', reasons: ['passive']},
                {term: '為る', source: '為せる',         rule: 'vs', reasons: ['causative']},
                {term: '為る', source: '為させる',       rule: 'vs', reasons: ['causative']},
                {term: '為る', source: '為せられる',     rule: 'vs', reasons: ['causative', 'potential or passive']},
                {term: '為る', source: '為させられる',   rule: 'vs', reasons: ['causative', 'potential or passive']},
                {term: '為る', source: '為ろ',           rule: 'vs', reasons: ['imperative']},
                {term: '為る', source: '為ない',         rule: 'vs', reasons: ['negative']},
                {term: '為る', source: '為ません',       rule: 'vs', reasons: ['polite negative']},
                {term: '為る', source: '為なかった',     rule: 'vs', reasons: ['negative', 'past']},
                {term: '為る', source: '為ませんでした', rule: 'vs', reasons: ['polite past negative']},
                {term: '為る', source: '為なくて',       rule: 'vs', reasons: ['negative', '-te']},
                {term: '為る', source: '為られない',     rule: 'vs', reasons: ['potential or passive', 'negative']},
                {term: '為る', source: '為れない',       rule: 'vs', reasons: ['passive', 'negative']},
                {term: '為る', source: '為せない',       rule: 'vs', reasons: ['causative', 'negative']},
                {term: '為る', source: '為させない',     rule: 'vs', reasons: ['causative', 'negative']},
                {term: '為る', source: '為せられない',   rule: 'vs', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '為る', source: '為させられない', rule: 'vs', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '為る', source: '為るな',         rule: 'vs', reasons: ['imperative negative']},

                {term: '為る', source: '為れば',         rule: 'vs', reasons: ['-ba']},
                {term: '為る', source: '為ちゃう',       rule: 'vs', reasons: ['-chau']},
                {term: '為る', source: '為なさい',       rule: 'vs', reasons: ['-nasai']},
                {term: '為る', source: '為そう',         rule: 'vs', reasons: ['-sou']},
                {term: '為る', source: '為すぎる',       rule: 'vs', reasons: ['-sugiru']},
                {term: '為る', source: '為たい',         rule: 'vs', reasons: ['-tai']},
                {term: '為る', source: '為たら',         rule: 'vs', reasons: ['-tara']},
                {term: '為る', source: '為たり',         rule: 'vs', reasons: ['-tari']},
                {term: '為る', source: '為ず',           rule: 'vs', reasons: ['-zu']},
                {term: '為る', source: '為ぬ',           rule: 'vs', reasons: ['-nu']},
                // ['masu stem']
                {term: '為る', source: '為ましょう',     rule: 'vs', reasons: ['polite volitional']},
                {term: '為る', source: '為よう',         rule: 'vs', reasons: ['volitional']},
                // ['causative passive']
                {term: '為る', source: '為とく',         rule: 'vs', reasons: ['-toku']},
                {term: '為る', source: '為ている',       rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: '為る', source: '為ておる',       rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: '為る', source: '為てる',         rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: '為る', source: '為とる',         rule: 'vs', reasons: ['-te', 'progressive or perfect']},

                {term: 'する', source: 'する',           rule: 'vs', reasons: []},
                {term: 'する', source: 'します',         rule: 'vs', reasons: ['polite']},
                {term: 'する', source: 'した',           rule: 'vs', reasons: ['past']},
                {term: 'する', source: 'しました',       rule: 'vs', reasons: ['polite past']},
                {term: 'する', source: 'して',           rule: 'vs', reasons: ['-te']},
                {term: 'する', source: 'せられる',       rule: 'vs', reasons: ['potential or passive']},
                {term: 'する', source: 'される',         rule: 'vs', reasons: ['passive']},
                {term: 'する', source: 'させる',         rule: 'vs', reasons: ['causative']},
                {term: 'する', source: 'せさせる',       rule: 'vs', reasons: ['causative']},
                {term: 'する', source: 'させられる',     rule: 'vs', reasons: ['causative', 'potential or passive']},
                {term: 'する', source: 'せさせられる',   rule: 'vs', reasons: ['causative', 'potential or passive']},
                {term: 'する', source: 'しろ',           rule: 'vs', reasons: ['imperative']},
                {term: 'する', source: 'しない',         rule: 'vs', reasons: ['negative']},
                {term: 'する', source: 'しません',       rule: 'vs', reasons: ['polite negative']},
                {term: 'する', source: 'しなかった',     rule: 'vs', reasons: ['negative', 'past']},
                {term: 'する', source: 'しませんでした', rule: 'vs', reasons: ['polite past negative']},
                {term: 'する', source: 'しなくて',       rule: 'vs', reasons: ['negative', '-te']},
                {term: 'する', source: 'せられない',     rule: 'vs', reasons: ['potential or passive', 'negative']},
                {term: 'する', source: 'されない',       rule: 'vs', reasons: ['passive', 'negative']},
                {term: 'する', source: 'させない',       rule: 'vs', reasons: ['causative', 'negative']},
                {term: 'する', source: 'せさせない',     rule: 'vs', reasons: ['causative', 'negative']},
                {term: 'する', source: 'させられない',   rule: 'vs', reasons: ['causative', 'potential or passive', 'negative']},
                {term: 'する', source: 'せさせられない', rule: 'vs', reasons: ['causative', 'potential or passive', 'negative']},
                {term: 'する', source: 'するな',         rule: 'vs', reasons: ['imperative negative']},

                {term: 'する', source: 'すれば',         rule: 'vs', reasons: ['-ba']},
                {term: 'する', source: 'しちゃう',       rule: 'vs', reasons: ['-chau']},
                {term: 'する', source: 'しなさい',       rule: 'vs', reasons: ['-nasai']},
                {term: 'する', source: 'しそう',         rule: 'vs', reasons: ['-sou']},
                {term: 'する', source: 'しすぎる',       rule: 'vs', reasons: ['-sugiru']},
                {term: 'する', source: 'したい',         rule: 'vs', reasons: ['-tai']},
                {term: 'する', source: 'したら',         rule: 'vs', reasons: ['-tara']},
                {term: 'する', source: 'したり',         rule: 'vs', reasons: ['-tari']},
                {term: 'する', source: 'せず',           rule: 'vs', reasons: ['-zu']},
                {term: 'する', source: 'せぬ',           rule: 'vs', reasons: ['-nu']},
                // ['masu stem']
                {term: 'する', source: 'しましょう',     rule: 'vs', reasons: ['polite volitional']},
                {term: 'する', source: 'しよう',         rule: 'vs', reasons: ['volitional']},
                // ['causative passive']
                {term: 'する', source: 'しとく',         rule: 'vs', reasons: ['-toku']},
                {term: 'する', source: 'している',       rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: 'する', source: 'しておる',       rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: 'する', source: 'してる',         rule: 'vs', reasons: ['-te', 'progressive or perfect']},
                {term: 'する', source: 'しとる',         rule: 'vs', reasons: ['-te', 'progressive or perfect']},

                {term: '来る', source: '来る',           rule: 'vk', reasons: []},
                {term: '来る', source: '来ます',         rule: 'vk', reasons: ['polite']},
                {term: '来る', source: '来た',           rule: 'vk', reasons: ['past']},
                {term: '来る', source: '来ました',       rule: 'vk', reasons: ['polite past']},
                {term: '来る', source: '来て',           rule: 'vk', reasons: ['-te']},
                {term: '来る', source: '来られる',       rule: 'vk', reasons: ['potential or passive']},
                {term: '来る', source: '来られる',       rule: 'vk', reasons: ['potential or passive']},
                {term: '来る', source: '来させる',       rule: 'vk', reasons: ['causative']},
                {term: '来る', source: '来させられる',   rule: 'vk', reasons: ['causative', 'potential or passive']},
                {term: '来る', source: '来い',           rule: 'vk', reasons: ['imperative']},
                {term: '来る', source: '来ない',         rule: 'vk', reasons: ['negative']},
                {term: '来る', source: '来ません',       rule: 'vk', reasons: ['polite negative']},
                {term: '来る', source: '来なかった',     rule: 'vk', reasons: ['negative', 'past']},
                {term: '来る', source: '来ませんでした', rule: 'vk', reasons: ['polite past negative']},
                {term: '来る', source: '来なくて',       rule: 'vk', reasons: ['negative', '-te']},
                {term: '来る', source: '来られない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: '来る', source: '来られない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: '来る', source: '来させない',     rule: 'vk', reasons: ['causative', 'negative']},
                {term: '来る', source: '来させられない', rule: 'vk', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '来る', source: '来るな',         rule: 'vk', reasons: ['imperative negative']},

                {term: '来る', source: '来れば',         rule: 'vk', reasons: ['-ba']},
                {term: '来る', source: '来ちゃう',       rule: 'vk', reasons: ['-chau']},
                {term: '来る', source: '来なさい',       rule: 'vk', reasons: ['-nasai']},
                {term: '来る', source: '来そう',         rule: 'vk', reasons: ['-sou']},
                {term: '来る', source: '来すぎる',       rule: 'vk', reasons: ['-sugiru']},
                {term: '来る', source: '来たい',         rule: 'vk', reasons: ['-tai']},
                {term: '来る', source: '来たら',         rule: 'vk', reasons: ['-tara']},
                {term: '来る', source: '来たり',         rule: 'vk', reasons: ['-tari']},
                {term: '来る', source: '来ず',           rule: 'vk', reasons: ['-zu']},
                {term: '来る', source: '来ぬ',           rule: 'vk', reasons: ['-nu']},
                {term: '来る', source: '来',             rule: 'vk', reasons: ['masu stem']},
                {term: '来る', source: '来ましょう',     rule: 'vk', reasons: ['polite volitional']},
                {term: '来る', source: '来よう',         rule: 'vk', reasons: ['volitional']},
                // ['causative passive']
                {term: '来る', source: '来とく',         rule: 'vk', reasons: ['-toku']},
                {term: '来る', source: '来ている',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '来る', source: '来ておる',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '来る', source: '来てる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '来る', source: '来とる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},

                {term: '來る', source: '來る',           rule: 'vk', reasons: []},
                {term: '來る', source: '來ます',         rule: 'vk', reasons: ['polite']},
                {term: '來る', source: '來た',           rule: 'vk', reasons: ['past']},
                {term: '來る', source: '來ました',       rule: 'vk', reasons: ['polite past']},
                {term: '來る', source: '來て',           rule: 'vk', reasons: ['-te']},
                {term: '來る', source: '來られる',       rule: 'vk', reasons: ['potential or passive']},
                {term: '來る', source: '來られる',       rule: 'vk', reasons: ['potential or passive']},
                {term: '來る', source: '來させる',       rule: 'vk', reasons: ['causative']},
                {term: '來る', source: '來させられる',   rule: 'vk', reasons: ['causative', 'potential or passive']},
                {term: '來る', source: '來い',           rule: 'vk', reasons: ['imperative']},
                {term: '來る', source: '來ない',         rule: 'vk', reasons: ['negative']},
                {term: '來る', source: '來ません',       rule: 'vk', reasons: ['polite negative']},
                {term: '來る', source: '來なかった',     rule: 'vk', reasons: ['negative', 'past']},
                {term: '來る', source: '來ませんでした', rule: 'vk', reasons: ['polite past negative']},
                {term: '來る', source: '來なくて',       rule: 'vk', reasons: ['negative', '-te']},
                {term: '來る', source: '來られない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: '來る', source: '來られない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: '來る', source: '來させない',     rule: 'vk', reasons: ['causative', 'negative']},
                {term: '來る', source: '來させられない', rule: 'vk', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '來る', source: '來るな',         rule: 'vk', reasons: ['imperative negative']},

                {term: '來る', source: '來れば',         rule: 'vk', reasons: ['-ba']},
                {term: '來る', source: '來ちゃう',       rule: 'vk', reasons: ['-chau']},
                {term: '來る', source: '來なさい',       rule: 'vk', reasons: ['-nasai']},
                {term: '來る', source: '來そう',         rule: 'vk', reasons: ['-sou']},
                {term: '來る', source: '來すぎる',       rule: 'vk', reasons: ['-sugiru']},
                {term: '來る', source: '來たい',         rule: 'vk', reasons: ['-tai']},
                {term: '來る', source: '來たら',         rule: 'vk', reasons: ['-tara']},
                {term: '來る', source: '來たり',         rule: 'vk', reasons: ['-tari']},
                {term: '來る', source: '來ず',           rule: 'vk', reasons: ['-zu']},
                {term: '來る', source: '來ぬ',           rule: 'vk', reasons: ['-nu']},
                {term: '來る', source: '來',             rule: 'vk', reasons: ['masu stem']},
                {term: '來る', source: '來ましょう',     rule: 'vk', reasons: ['polite volitional']},
                {term: '來る', source: '來よう',         rule: 'vk', reasons: ['volitional']},
                // ['causative passive']
                {term: '來る', source: '來とく',         rule: 'vk', reasons: ['-toku']},
                {term: '來る', source: '來ている',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '來る', source: '來ておる',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '來る', source: '來てる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: '來る', source: '來とる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},

                {term: 'くる', source: 'くる',           rule: 'vk', reasons: []},
                {term: 'くる', source: 'きます',         rule: 'vk', reasons: ['polite']},
                {term: 'くる', source: 'きた',           rule: 'vk', reasons: ['past']},
                {term: 'くる', source: 'きました',       rule: 'vk', reasons: ['polite past']},
                {term: 'くる', source: 'きて',           rule: 'vk', reasons: ['-te']},
                {term: 'くる', source: 'こられる',       rule: 'vk', reasons: ['potential or passive']},
                {term: 'くる', source: 'こられる',       rule: 'vk', reasons: ['potential or passive']},
                {term: 'くる', source: 'こさせる',       rule: 'vk', reasons: ['causative']},
                {term: 'くる', source: 'こさせられる',   rule: 'vk', reasons: ['causative', 'potential or passive']},
                {term: 'くる', source: 'こい',           rule: 'vk', reasons: ['imperative']},
                {term: 'くる', source: 'こない',         rule: 'vk', reasons: ['negative']},
                {term: 'くる', source: 'きません',       rule: 'vk', reasons: ['polite negative']},
                {term: 'くる', source: 'こなかった',     rule: 'vk', reasons: ['negative', 'past']},
                {term: 'くる', source: 'きませんでした', rule: 'vk', reasons: ['polite past negative']},
                {term: 'くる', source: 'こなくて',       rule: 'vk', reasons: ['negative', '-te']},
                {term: 'くる', source: 'こられない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: 'くる', source: 'こられない',     rule: 'vk', reasons: ['potential or passive', 'negative']},
                {term: 'くる', source: 'こさせない',     rule: 'vk', reasons: ['causative', 'negative']},
                {term: 'くる', source: 'こさせられない', rule: 'vk', reasons: ['causative', 'potential or passive', 'negative']},
                {term: 'くる', source: 'くるな',         rule: 'vk', reasons: ['imperative negative']},

                {term: 'くる', source: 'くれば',         rule: 'vk', reasons: ['-ba']},
                {term: 'くる', source: 'きちゃう',       rule: 'vk', reasons: ['-chau']},
                {term: 'くる', source: 'きなさい',       rule: 'vk', reasons: ['-nasai']},
                {term: 'くる', source: 'きそう',         rule: 'vk', reasons: ['-sou']},
                {term: 'くる', source: 'きすぎる',       rule: 'vk', reasons: ['-sugiru']},
                {term: 'くる', source: 'きたい',         rule: 'vk', reasons: ['-tai']},
                {term: 'くる', source: 'きたら',         rule: 'vk', reasons: ['-tara']},
                {term: 'くる', source: 'きたり',         rule: 'vk', reasons: ['-tari']},
                {term: 'くる', source: 'こず',           rule: 'vk', reasons: ['-zu']},
                {term: 'くる', source: 'こぬ',           rule: 'vk', reasons: ['-nu']},
                {term: 'くる', source: 'き',             rule: 'vk', reasons: ['masu stem']},
                {term: 'くる', source: 'きましょう',     rule: 'vk', reasons: ['polite volitional']},
                {term: 'くる', source: 'こよう',         rule: 'vk', reasons: ['volitional']},
                // ['causative passive']
                {term: 'くる', source: 'きとく',         rule: 'vk', reasons: ['-toku']},
                {term: 'くる', source: 'きている',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: 'くる', source: 'きておる',       rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: 'くる', source: 'きてる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},
                {term: 'くる', source: 'きとる',         rule: 'vk', reasons: ['-te', 'progressive or perfect']},

                // Zuru verbs
                {term: '論ずる', source: '論ずる',           rule: 'vz', reasons: []},
                {term: '論ずる', source: '論じます',         rule: 'vz', reasons: ['polite']},
                {term: '論ずる', source: '論じた',           rule: 'vz', reasons: ['past']},
                {term: '論ずる', source: '論じました',       rule: 'vz', reasons: ['polite past']},
                {term: '論ずる', source: '論じて',           rule: 'vz', reasons: ['-te']},
                {term: '論ずる', source: '論ぜられる',       rule: 'vz', reasons: ['potential or passive']},
                {term: '論ずる', source: '論じされる',       rule: 'vz', reasons: ['passive']},
                {term: '論ずる', source: '論ぜされる',       rule: 'vz', reasons: ['passive']},
                {term: '論ずる', source: '論じさせる',       rule: 'vz', reasons: ['causative']},
                {term: '論ずる', source: '論ぜさせる',       rule: 'vz', reasons: ['causative']},
                {term: '論ずる', source: '論じさせられる',   rule: 'vz', reasons: ['causative', 'potential or passive']},
                {term: '論ずる', source: '論ぜさせられる',   rule: 'vz', reasons: ['causative', 'potential or passive']},
                {term: '論ずる', source: '論じろ',           rule: 'vz', reasons: ['imperative']},
                {term: '論ずる', source: '論じない',         rule: 'vz', reasons: ['negative']},
                {term: '論ずる', source: '論じません',       rule: 'vz', reasons: ['polite negative']},
                {term: '論ずる', source: '論じなかった',     rule: 'vz', reasons: ['negative', 'past']},
                {term: '論ずる', source: '論じませんでした', rule: 'vz', reasons: ['polite past negative']},
                {term: '論ずる', source: '論じなくて',       rule: 'vz', reasons: ['negative', '-te']},
                {term: '論ずる', source: '論ぜられない',     rule: 'vz', reasons: ['potential or passive', 'negative']},
                {term: '論ずる', source: '論じされない',     rule: 'vz', reasons: ['passive', 'negative']},
                {term: '論ずる', source: '論ぜされない',     rule: 'vz', reasons: ['passive', 'negative']},
                {term: '論ずる', source: '論じさせない',     rule: 'vz', reasons: ['causative', 'negative']},
                {term: '論ずる', source: '論ぜさせない',     rule: 'vz', reasons: ['causative', 'negative']},
                {term: '論ずる', source: '論じさせられない', rule: 'vz', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '論ずる', source: '論ぜさせられない', rule: 'vz', reasons: ['causative', 'potential or passive', 'negative']},
                {term: '論ずる', source: '論ずるな',         rule: 'vz', reasons: ['imperative negative']},

                {term: '論ずる', source: '論ずれば',         rule: 'vz', reasons: ['-ba']},
                {term: '論ずる', source: '論じちゃう',       rule: 'vz', reasons: ['-chau']},
                {term: '論ずる', source: '論じなさい',       rule: 'vz', reasons: ['-nasai']},
                {term: '論ずる', source: '論じそう',         rule: 'vz', reasons: ['-sou']},
                {term: '論ずる', source: '論じすぎる',       rule: 'vz', reasons: ['-sugiru']},
                {term: '論ずる', source: '論じたい',         rule: 'vz', reasons: ['-tai']},
                {term: '論ずる', source: '論じたら',         rule: 'vz', reasons: ['-tara']},
                {term: '論ずる', source: '論じたり',         rule: 'vz', reasons: ['-tari']},
                {term: '論ずる', source: '論ぜず',           rule: 'vz', reasons: ['-zu']},
                {term: '論ずる', source: '論ぜぬ',           rule: 'vz', reasons: ['-nu']},
                // ['masu stem']
                {term: '論ずる', source: '論じましょう',     rule: 'vz', reasons: ['polite volitional']},
                {term: '論ずる', source: '論じよう',         rule: 'vz', reasons: ['volitional']},
                // ['causative passive']
                {term: '論ずる', source: '論じとく',         rule: 'vz', reasons: ['-toku']},
                {term: '論ずる', source: '論じている',       rule: 'vz', reasons: ['-te', 'progressive or perfect']},
                {term: '論ずる', source: '論じておる',       rule: 'vz', reasons: ['-te', 'progressive or perfect']},
                {term: '論ずる', source: '論じてる',         rule: 'vz', reasons: ['-te', 'progressive or perfect']},
                {term: '論ずる', source: '論じとる',         rule: 'vz', reasons: ['-te', 'progressive or perfect']},

                // Uncommon irregular verbs
                {term: 'のたまう', source: 'のたもうて',   rule: 'v5', reasons: ['-te']},
                {term: 'のたまう', source: 'のたもうた',   rule: 'v5', reasons: ['past']},
                {term: 'のたまう', source: 'のたもうたら', rule: 'v5', reasons: ['-tara']},
                {term: 'のたまう', source: 'のたもうたり', rule: 'v5', reasons: ['-tari']},

                {term: 'おう', source: 'おうて', rule: 'v5', reasons: ['-te']},
                {term: 'こう', source: 'こうて', rule: 'v5', reasons: ['-te']},
                {term: 'そう', source: 'そうて', rule: 'v5', reasons: ['-te']},
                {term: 'とう', source: 'とうて', rule: 'v5', reasons: ['-te']},
                {term: '請う', source: '請うて', rule: 'v5', reasons: ['-te']},
                {term: '乞う', source: '乞うて', rule: 'v5', reasons: ['-te']},
                {term: '恋う', source: '恋うて', rule: 'v5', reasons: ['-te']},
                {term: '問う', source: '問うて', rule: 'v5', reasons: ['-te']},
                {term: '負う', source: '負うて', rule: 'v5', reasons: ['-te']},
                {term: '沿う', source: '沿うて', rule: 'v5', reasons: ['-te']},
                {term: '添う', source: '添うて', rule: 'v5', reasons: ['-te']},
                {term: '副う', source: '副うて', rule: 'v5', reasons: ['-te']},
                {term: '厭う', source: '厭うて', rule: 'v5', reasons: ['-te']},

                {term: 'おう', source: 'おうた', rule: 'v5', reasons: ['past']},
                {term: 'こう', source: 'こうた', rule: 'v5', reasons: ['past']},
                {term: 'そう', source: 'そうた', rule: 'v5', reasons: ['past']},
                {term: 'とう', source: 'とうた', rule: 'v5', reasons: ['past']},
                {term: '請う', source: '請うた', rule: 'v5', reasons: ['past']},
                {term: '乞う', source: '乞うた', rule: 'v5', reasons: ['past']},
                {term: '恋う', source: '恋うた', rule: 'v5', reasons: ['past']},
                {term: '問う', source: '問うた', rule: 'v5', reasons: ['past']},
                {term: '負う', source: '負うた', rule: 'v5', reasons: ['past']},
                {term: '沿う', source: '沿うた', rule: 'v5', reasons: ['past']},
                {term: '添う', source: '添うた', rule: 'v5', reasons: ['past']},
                {term: '副う', source: '副うた', rule: 'v5', reasons: ['past']},
                {term: '厭う', source: '厭うた', rule: 'v5', reasons: ['past']},

                {term: 'おう', source: 'おうたら', rule: 'v5', reasons: ['-tara']},
                {term: 'こう', source: 'こうたら', rule: 'v5', reasons: ['-tara']},
                {term: 'そう', source: 'そうたら', rule: 'v5', reasons: ['-tara']},
                {term: 'とう', source: 'とうたら', rule: 'v5', reasons: ['-tara']},
                {term: '請う', source: '請うたら', rule: 'v5', reasons: ['-tara']},
                {term: '乞う', source: '乞うたら', rule: 'v5', reasons: ['-tara']},
                {term: '恋う', source: '恋うたら', rule: 'v5', reasons: ['-tara']},
                {term: '問う', source: '問うたら', rule: 'v5', reasons: ['-tara']},
                {term: '負う', source: '負うたら', rule: 'v5', reasons: ['-tara']},
                {term: '沿う', source: '沿うたら', rule: 'v5', reasons: ['-tara']},
                {term: '添う', source: '添うたら', rule: 'v5', reasons: ['-tara']},
                {term: '副う', source: '副うたら', rule: 'v5', reasons: ['-tara']},
                {term: '厭う', source: '厭うたら', rule: 'v5', reasons: ['-tara']},

                {term: 'おう', source: 'おうたり', rule: 'v5', reasons: ['-tari']},
                {term: 'こう', source: 'こうたり', rule: 'v5', reasons: ['-tari']},
                {term: 'そう', source: 'そうたり', rule: 'v5', reasons: ['-tari']},
                {term: 'とう', source: 'とうたり', rule: 'v5', reasons: ['-tari']},
                {term: '請う', source: '請うたり', rule: 'v5', reasons: ['-tari']},
                {term: '乞う', source: '乞うたり', rule: 'v5', reasons: ['-tari']},
                {term: '恋う', source: '恋うたり', rule: 'v5', reasons: ['-tari']},
                {term: '問う', source: '問うたり', rule: 'v5', reasons: ['-tari']},
                {term: '負う', source: '負うたり', rule: 'v5', reasons: ['-tari']},
                {term: '沿う', source: '沿うたり', rule: 'v5', reasons: ['-tari']},
                {term: '添う', source: '添うたり', rule: 'v5', reasons: ['-tari']},
                {term: '副う', source: '副うたり', rule: 'v5', reasons: ['-tari']},
                {term: '厭う', source: '厭うたり', rule: 'v5', reasons: ['-tari']},

                // Combinations
                {term: '抱き抱える', source: '抱き抱えていなければ', rule: 'v1', reasons: ['-te', 'progressive or perfect', 'negative', '-ba']},
                {term: '抱きかかえる', source: '抱きかかえていなければ', rule: 'v1', reasons: ['-te', 'progressive or perfect', 'negative', '-ba']},
                {term: '打ち込む', source: '打ち込んでいませんでした', rule: 'v5', reasons: ['-te', 'progressive or perfect', 'polite past negative']},
                {term: '食べる', source: '食べさせられたくなかった', rule: 'v1', reasons: ['causative', 'potential or passive', '-tai', 'negative', 'past']}
            ]
        },
        {
            valid: false,
            tests: [
                {term: 'する', source: 'すます',         rule: 'vs'},
                {term: 'する', source: 'すた',           rule: 'vs'},
                {term: 'する', source: 'すました',       rule: 'vs'},
                {term: 'する', source: 'すて',           rule: 'vs'},
                {term: 'する', source: 'すれる',         rule: 'vs'},
                {term: 'する', source: 'すせる',         rule: 'vs'},
                {term: 'する', source: 'すせられる',     rule: 'vs'},
                {term: 'する', source: 'すろ',           rule: 'vs'},
                {term: 'する', source: 'すない',         rule: 'vs'},
                {term: 'する', source: 'すません',       rule: 'vs'},
                {term: 'する', source: 'すなかった',     rule: 'vs'},
                {term: 'する', source: 'すませんでした', rule: 'vs'},
                {term: 'する', source: 'すなくて',       rule: 'vs'},
                {term: 'する', source: 'すれない',       rule: 'vs'},
                {term: 'する', source: 'すせない',       rule: 'vs'},
                {term: 'する', source: 'すせられない',   rule: 'vs'},

                {term: 'くる', source: 'くます',         rule: 'vk'},
                {term: 'くる', source: 'くた',           rule: 'vk'},
                {term: 'くる', source: 'くました',       rule: 'vk'},
                {term: 'くる', source: 'くて',           rule: 'vk'},
                {term: 'くる', source: 'くられる',       rule: 'vk'},
                {term: 'くる', source: 'くられる',       rule: 'vk'},
                {term: 'くる', source: 'くさせる',       rule: 'vk'},
                {term: 'くる', source: 'くさせられる',   rule: 'vk'},
                {term: 'くる', source: 'くい',           rule: 'vk'},
                {term: 'くる', source: 'くない',         rule: 'vk'},
                {term: 'くる', source: 'くません',       rule: 'vk'},
                {term: 'くる', source: 'くなかった',     rule: 'vk'},
                {term: 'くる', source: 'くませんでした', rule: 'vk'},
                {term: 'くる', source: 'くなくて',       rule: 'vk'},
                {term: 'くる', source: 'くられない',     rule: 'vk'},
                {term: 'くる', source: 'くられない',     rule: 'vk'},
                {term: 'くる', source: 'くさせない',     rule: 'vk'},
                {term: 'くる', source: 'くさせられない', rule: 'vk'}
            ]
        }
    ];

    const vm = new VM();
    vm.execute(['bg/js/deinflector.js']);
    const [Deinflector] = vm.get(['Deinflector']);

    const deinflectionReasions = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ext', 'bg/lang/deinflect.json')));
    const deinflector = new Deinflector(deinflectionReasions);

    for (const {valid, tests} of data) {
        for (const {source, term, rule, reasons} of tests) {
            const {has, reasons: actualReasons} = hasTermReasons(Deinflector, deinflector, source, term, rule, reasons);
            let message = `${source} ${valid ? 'does not have' : 'has'} term candidate ${JSON.stringify(term)}`;
            if (typeof rule !== 'undefined') {
                message += ` with rule ${JSON.stringify(rule)}`;
            }
            if (typeof reasons !== 'undefined') {
                message += (typeof rule !== 'undefined' ? ' and' : ' with');
                message += ` reasons ${JSON.stringify(reasons)}`;
            }
            if (actualReasons !== null) {
                message += ` (actual reasons: ${JSON.stringify(actualReasons)})`;
            }
            assert.strictEqual(has, valid, message);
        }
    }
}


function main() {
    testDeinflections();
}


if (require.main === module) { testMain(main); }