Module:User:Theknightwho/la-verb

local m_utilities = require("Module:utilities") local m_table = require("Module:table") -- FIXME, port remaining functions to Module:table and use it instead local ut = require("Module:utils") local m_links = require("Module:links") local make_link = m_links.full_link local m_la_headword = require("Module:la-headword") local m_la_utilities = require("Module:la-utilities") local m_para = require("Module:parameters")

-- TODO: -- 1. (DONE) detect_decl_and_subtypes doesn't do anything with perf_stem or supine_stem. -- 2. (DONE) Should error on bad subtypes. -- 3. Make sure Google Books link still works. -- 4. (DONE) Add 4++ that has alternative perfects -īvī/-iī. -- 5. (DONE) If sup but no perf, allow passive perfect forms unless no-pasv-perf. -- 6. (DONE) Remove no-actv-perf. -- 7. (DONE) Support plural prefix/suffix and plural passive prefix/suffix -- -- If enabled, compare this module with new version of module to make -- sure all conjugations are the same. local test_new_la_verb_module = false

local export = {}

local lang = require("Module:languages").getByCode("la")

local title = mw.title.getCurrentTitle local NAMESPACE = title.nsText local PAGENAME = title.text

-- Conjugations are the functions that do the actual -- conjugating by creating the forms of a basic verb. -- They are defined further down. local conjugations = {}

-- Check if this verb is reconstructed -- i.e. the pagename is Reconstruction:Latin/... local reconstructed = NAMESPACE == "Reconstruction" and PAGENAME:find("^Latin/")

-- Forward functions

local postprocess local make_pres_1st local make_pres_2nd local make_pres_3rd local make_pres_3rd_io local make_pres_4th local make_perf_and_supine local make_perf local make_deponent_perf local make_supine local make_sigm local make_table local make_indc_rows local make_subj_rows local make_impr_rows local make_nonfin_rows local make_vn_rows local make_footnotes local override local checkexist local checkirregular local flatten_values local link_google_books

local split = mw.text.split local find = mw.ustring.find local len = mw.ustring.len local match = mw.ustring.match local sub = mw.ustring.sub local gsub = mw.ustring.gsub local toNFD = mw.ustring.toNFD

-- version of gsub that discards all but the first return value local function gsub1(term, foo, bar) local retval = gsub(term, foo, bar) return retval end

local function cfind(str, text) -- Constant version of :find return str:find(text, nil, true) end

local function form_is_empty(form) return not form or form == "" or form == "-" or form == "—" or form == "&mdash;" or (		type(form) == "table" and (form[1] == "" or form[1] == "-" or form[1] == "—" or form[1] == "&mdash;")	) end

local function initialize_slots local generic_slots = {} local non_generic_slots = {} local function handle_slot(slot, generic) if generic then table.insert(generic_slots, slot) else table.insert(non_generic_slots, slot) end end for _, v in ipairs({"actv", "pasv"}) do		local function handle_tense(t, mood) local non_pers_slot = t .. "_" .. v .. "_" .. mood handle_slot(non_pers_slot, true) for _, p in ipairs({"1s", "2s", "3s", "1p", "2p", "3p"}) do handle_slot(p .. "_" .. non_pers_slot, false) end end for _, t in ipairs({"pres", "impf", "futr", "perf", "plup", "futp", "sigf"}) do			handle_tense(t, "indc") end for _, t in ipairs({"pres", "impf", "perf", "plup", "siga"}) do			handle_tense(t, "subj") end for _, t in ipairs({"pres", "futr"}) do			handle_tense(t, "impr") end end for _, f in ipairs({"inf", "ptc"}) do		for _, t in ipairs({"pres_actv", "perf_actv", "futr_actv", "pres_pasv", "perf_pasv", "futr_pasv"}) do handle_slot(t .. "_" .. f, false) end end for _, n in ipairs({"ger_gen", "ger_dat", "ger_acc", "ger_abl", "sup_acc", "sup_abl"}) do		handle_slot(n, false) end return non_generic_slots, generic_slots end

local non_generic_slots, generic_slots = initialize_slots

local potential_lemma_slots = { "1s_pres_actv_indc", -- regular "3s_pres_actv_indc", -- impersonal "1s_perf_actv_indc", -- coepī "3s_perf_actv_indc", -- doesn't occur? }

-- Iterate over all the "slots" associated with a verb declension, where a slot -- is e.g. 1s_pres_actv_indc (a non-generic slot), pres_actv_indc (a generic slot), -- or linked_1s_pres_actv_indc (a linked slot). Only include the generic and/or linked -- slots if called for. local function iter_slots(include_generic, include_linked) -- stage == 1: non-generic slots -- stage == 2: generic slots -- stage == 3: linked slots local stage = 1 local slotnum = 0 local max_slotnum = #non_generic_slots local function iter slotnum = slotnum + 1 if slotnum > max_slotnum then slotnum = 1 stage = stage + 1 if stage == 2 then if include_generic then max_slotnum = #generic_slots else stage = stage + 1 end end if stage == 3 then if include_linked then max_slotnum = #potential_lemma_slots else stage = stage + 1 end end if stage > 3 then return nil end end if stage == 1 then return non_generic_slots[slotnum] elseif stage == 2 then return generic_slots[slotnum] else return "linked_" .. potential_lemma_slots[slotnum] end end return iter end

local function ine(val) if val == "" then return nil else return val end end

local function track(page) require("Module:debug").track("la-verb/" .. page) return true end

-- For a given form, we allow either strings (a single form) or lists of forms, -- and treat strings equivalent to one-element lists. local function forms_equal(form1, form2) if type(form1) ~= "table" then form1 = {form1} end if type(form2) ~= "table" then form2 = {form2} end return m_table.deepEquals(form1, form2) end

local function concat_vals(val) if type(val) == "table" then return table.concat(val, ",") else return val end end

-- Construct a one- or two-part link. For reasons I don't understand, if we're in -- the reconstructed namespace (e.g. for the page Reconstruction:Latin/nuo), we -- need to construct a special type of link; full_link doesn't handle this -- correctly (although it tries ...). Ideally we should fix full_link instead of -- doing this. local function make_raw_link(page, display) if reconstructed then display = display or page page = lang:makeEntryName(page) return "" .. display .. "" elseif display then return "" .. display .. "" else return "" .. page .. "" end end

local function split_prefix_and_base(lemma, main_verbs) for _, main in ipairs(main_verbs) do local prefix = match(lemma, "^(.*)" .. main .. "$") if prefix then return prefix, main end end error("Argument " .. lemma .. " doesn't end in any of " .. table.concat(main_verbs, ",")) end

-- Given an ending (or possibly a full regex matching the entire lemma, if -- a regex group is present), return the base minus the ending, or nil if -- the ending doesn't match. local function extract_base(lemma, ending) if ending:find("%(") then		return match(lemma, ending)	else		return match(lemma, "^(.*)" .. ending .. "$")	end end

-- Given ENDINGS_AND_SUBTYPES (a list of pairs of endings with associated -- subtypes, where each pair consists of a single ending spec and a list of -- subtypes), check each ending in turn against LEMMA. If it matches, return -- the pair BASE, SUBTYPES where BASE is the remainder of LEMMA minus the -- ending, and SUBTYPES is the subtypes associated with the ending. If no -- endings match, throw an error if DECLTYPE is non-nil, mentioning the -- DECLTYPE (the user-specified declension); but if DECLTYPE is nil, just -- return the pair nil, nil. -- -- The ending spec in ENDINGS_AND_SUBTYPES is one of the following: -- -- 1. A simple string, e.g. "ātur", specifying an ending. -- 2. A regex that should match the entire lemma (it should be anchored at --   the beginning with ^ and at the end with $), and contains a single --   capturing group to match the base. local function get_subtype_by_ending(lemma, conjtype, specified_subtypes,		endings_and_subtypes) for _, ending_and_subtypes in ipairs(endings_and_subtypes) do		local ending = ending_and_subtypes[1] local subtypes = ending_and_subtypes[2] not_this_subtype = false for _, subtype in ipairs(subtypes) do -- A subtype is directly canceled by specifying -SUBTYPE. if specified_subtypes["-" .. subtype] then not_this_subtype = true break end end if not not_this_subtype then local base = extract_base(lemma, ending) if base then return base, subtypes end end end if conjtype then error("Unrecognized ending for conjugation-" .. conjtype .. " verb: " .. lemma) end return nil, nil end

local irreg_verbs_to_conj_type = { ["aiō"] = "3rd-io", ["aiiō"] = "3rd-io", ["ajō"] = "3rd-io", ["dīcō"] = "3rd", ["dūcō"] = "3rd", ["faciō"] = "3rd-io", ["fīō"] = "3rd", ["ferō"] = "3rd", ["inquam"] = "irreg", ["libet"] = "2nd", ["lubet"] = "2nd", ["licet"] = "2nd", ["volō"] = "irreg", ["mālō"] = "irreg", ["nōlō"] = "irreg", ["possum"] = "irreg", ["piget"] = "2nd", ["coepī"] = "irreg", ["sum"] = "irreg", ["edō"] = "3rd", ["dō"] = "1st", ["eō"] = "irreg", }

local function detect_decl_and_subtypes(args) local specs = split(args[1] or "", "%.") local subtypes = {} local conj_arg for i, spec in ipairs(specs) do		if i == 1 then conj_arg = spec else local begins_with_hyphen = find(spec, "^%-") spec = spec:gsub("%-", "") if begins_with_hyphen then spec = "-" .. spec end subtypes[spec] = true end end

local orig_lemma = args[2] or mw.title.getCurrentTitle.subpageText orig_lemma = gsub1(orig_lemma, "o$", "ō") local lemma = m_links.remove_links(orig_lemma) local base, conjtype, conj_subtype, detected_subtypes local base_conj_arg, auto_perf_supine = match(conj_arg, "^([124])(%+%+?)$") if base_conj_arg then if auto_perf_supine == "++" and base_conj_arg ~= "4" then error("Conjugation types 1++ and 2++ not allowed") end conj_arg = base_conj_arg end if sub(orig_lemma, 1, 1) == "-" then subtypes.suffix = true end local auto_perf, auto_supine, auto_sigm if subtypes.sigm or subtypes.sigmpasv or subtypes.suffix then auto_sigm = true end

if conj_arg == "1" then conjtype = "1st" base, detected_subtypes = get_subtype_by_ending(lemma, "1", subtypes, {			{"ō", {}},			{"or", {"depon"}},			{"at", {"impers"}},			{"ātur", {"depon", "impers"}},			{"ī", {"perfaspres"}},		}) if auto_perf_supine then if subtypes.perfaspres then auto_perf = base else auto_perf = base .. "āv" auto_supine = base .. "āt" end end if auto_sigm then auto_sigm = base .. "āss" end if subtypes.suffix then subtypes.p3inf = true subtypes.sigmpasv = true end elseif conj_arg == "2" then conjtype = "2nd" base, detected_subtypes = get_subtype_by_ending(lemma, "2", subtypes, {			{"eō", {}},			{"eor", {"depon"}},			{"et", {"impers"}},			{"ētur", {"depon", "impers"}},			{"ī", {"perfaspres"}},		}) if auto_perf_supine then if subtypes.perfaspres then auto_perf = base else auto_perf = base .. "u" auto_supine = base .. "it" end end if auto_sigm then auto_sigm = "-/ēss" end if subtypes.suffix then subtypes.sigmpasv = true end elseif conj_arg == "3" then base, detected_subtypes = get_subtype_by_ending(lemma, nil, subtypes, {			{"iō", {"I"}},			{"ior", {"depon", "I"}},		}) if base then conjtype = "3rd-io" else base, detected_subtypes = get_subtype_by_ending(lemma, "3", subtypes, {				{"ō", {}},				{"or", {"depon"}},				{"it", {"impers"}},				{"itur", {"depon", "impers"}},				{"ī", {"perfaspres"}},			}) if subtypes.I then conjtype = "3rd-io" else conjtype = "3rd" end end if subtypes.perfaspres then auto_perf = base end if subtypes.suffix then auto_perf = "-" auto_supine = "-" auto_sigm = "-" subtypes.sigmpasv = true end elseif conj_arg == "4" then conjtype = "4th" base, detected_subtypes = get_subtype_by_ending(lemma, "4", subtypes, {			{"iō", {}},			{"ior", {"depon"}},			{"it", {"impers"}},			{"ītur", {"depon", "impers"}},			{"ī", {"perfaspres"}},		}) if subtypes.perfaspres then auto_perf = base elseif auto_perf_supine == "++" then auto_perf = base .. "īv/" .. base .. "i" auto_supine = base .. "īt" elseif auto_perf_supine == "+" then auto_perf = base .. "īv" auto_supine = base .. "īt" end if auto_sigm then auto_sigm = base .. "īss" end if subtypes.suffix then subtypes.sigm = true end elseif conj_arg == "irreg" then conjtype = "irreg" local prefix prefix, base = split_prefix_and_base(lemma, {			"aiō",			"aiiō",			"ajō",			"dīcō",			"dūcō",			"faciō",			"fīō",			"ferō",			"inquam",			"libet",			"lubet",			"licet",			"volō",			"mālō",			"nōlō",			"possum",			"piget",			"coepī",			-- list sum after possum			"sum",			-- FIXME: Will praedō cause problems?			"edō",			-- list dō after edō			"dō",			"eō",		}) conj_subtype = irreg_verbs_to_conj_type[base] args[1] = m_la_utilities.strip_macrons(base) args[2] = prefix -- args[3] and args[4] are used by ferō and sum and stay where they are detected_subtypes = {} else error("Unrecognized conjugation '" .. conj_arg .. "'") end

for _, detected_subtype in ipairs(detected_subtypes) do		if detected_subtype == "impers" and subtypes["3only"] then -- 3only overrides impers else subtypes[detected_subtype] = true end end

if conjtype ~= "irreg" then args[1] = base local perf_stem, supine_stem if subtypes.depon or subtypes.semidepon or subtypes.perfaspres then supine_stem = args[3] or auto_supine if supine_stem == "-" and not subtypes.suffix then supine_stem = nil end if not supine_stem then if subtypes.depon or subtypes.semidepon then subtypes.noperf = true end subtypes.nosup = true end if subtypes.sigm or subtypes.sigmpasv then local sigm_stem = args[5] or auto_sigm if sigm_stem == "-" and not subtypes.suffix then sigm_stem = nil end args[5] = sigm_stem end args[2] = supine_stem args[3] = nil else perf_stem = args[3] or auto_perf if perf_stem == "-" and not subtypes.suffix then perf_stem = nil end if not perf_stem then subtypes.noperf = true end supine_stem = args[4] or auto_supine if supine_stem == "-" and not subtypes.suffix then supine_stem = nil end if not supine_stem then subtypes.nosup = true end if subtypes.sigm or subtypes.sigmpasv then local sigm_stem = args[5] or auto_sigm if sigm_stem == "-" and not subtypes.suffix then sigm_stem = nil end args[5] = sigm_stem end args[2] = perf_stem args[3] = supine_stem end args[4] = nil end

for subtype, _ in pairs(subtypes) do		if not m_la_headword.allowed_subtypes[subtype] and not m_la_headword.allowed_subtypes[sub(subtype, 2)] and not (conjtype == "3rd" and subtype == "-I") and not (conjtype == "3rd-io" and subtype == "I") and not (subtype == "nound" or subtype == "sigm" or subtype == "sigmpasv" or subtype == "suffix") then error("Unrecognized verb subtype " .. subtype) end end

return conjtype, conj_subtype, subtypes, orig_lemma, lemma end

-- The main new entry point. function export.show(frame) local parent_args = frame:getParent.args local data, typeinfo = export.make_data(parent_args) local domain = frame:getParent.args['search'] -- Test code to compare existing module to new one. if test_new_la_verb_module then local m_new_la_verb = require("Module:User:Benwing2/la-verb") local miscdata = { title = data.title, categories = data.categories, }		local new_parent_args = frame:getParent.args local newdata, newtypeinfo = m_new_la_verb.make_data(new_parent_args) local newmiscdata = { title = newdata.title, categories = newdata.categories, }		local all_verb_props = {"forms", "form_footnote_indices", "footnotes", "miscdata"} local difconj = false for _, prop in ipairs(all_verb_props) do			local table = prop == "miscdata" and miscdata or data[prop] local newtable = prop == "miscdata" and newmiscdata or newdata[prop] for key, val in pairs(table) do				local newval = newtable[key] if not forms_equal(val, newval) then -- Uncomment this to display the particular key and -- differing forms. --error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil")) difconj = true break end end if difconj then break end -- Do the comparison the other way as well in case of extra keys -- in the new table. for key, newval in pairs(newtable) do				local val = table[key] if not forms_equal(val, newval) then -- Uncomment this to display the particular key and -- differing forms. --error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil")) difconj = true break end end if difconj then break end end track(difconj and "different-conj" or "same-conj") end if typeinfo.subtypes.suffix then data.categories = {} end

-- Check if the links to the verb forms exist -- Has to happen after other categories are removed for suffixes checkexist(data)

if domain == nil then return make_table(data) .. m_utilities.format_categories(data.categories, lang) else local verb = data['forms']['1s_pres_actv_indc'] ~= nil and (..data['forms']['1s_pres_actv_indc'].. ) or 'verb' return link_google_books(verb, flatten_values(data['forms']), domain) end end

local function concat_forms(data, typeinfo, include_props) local ins_text = {} for key, val in pairs(data.forms) do		local ins_form = {} if type(val) ~= "table" then val = {val} end for _, v in ipairs(val) do			if not form_is_empty(v) then table.insert(ins_form,					gsub1(gsub1(gsub1(v, "|", "<!>"), "=", "<->"), ",", "<.>")				) end end if #ins_form > 0 then table.insert(ins_text, key .. "=" .. table.concat(ins_form, ",")) end end if include_props then table.insert(ins_text, "conj_type=" .. typeinfo.conj_type) if typeinfo.conj_subtype then table.insert(ins_text, "conj_subtype=" .. typeinfo.conj_subtype) end local subtypes = {} for subtype, _ in pairs(typeinfo.subtypes) do			table.insert(subtypes, subtype) end table.insert(ins_text, "subtypes=" .. table.concat(subtypes, ".")) end return table.concat(ins_text, "|") end

-- The entry point for 'la-generate-verb-forms' and 'la-generate-verb-props' -- to generate all verb forms/props. function export.generate_forms(frame) local include_props = frame.args["include_props"] local parent_args = frame:getParent.args local data, typeinfo = export.make_data(parent_args) return concat_forms(data, typeinfo, include_props) end

-- Add prefixes and suffixes to non-generic slots. The generic slots (e.g. -- perf_pasv_indc, whose text indicates to use the past passive participle + -- the present active indicative of sum), handle prefixes and suffixes -- themselves in make_perfect_passive. local function add_prefix_suffix(data, typeinfo) if not data.prefix and not data.suffix then return end

local active_prefix = data.prefix or "" local passive_prefix = data.passive_prefix or "" local plural_prefix = data.plural_prefix or "" local plural_passive_prefix = data.plural_passive_prefix or "" local active_prefix_no_links = m_links.remove_links(active_prefix) local passive_prefix_no_links = m_links.remove_links(passive_prefix) local plural_prefix_no_links = m_links.remove_links(plural_prefix) local plural_passive_prefix_no_links = m_links.remove_links(plural_passive_prefix)

local active_suffix = data.suffix or "" local passive_suffix = data.passive_suffix or "" local plural_suffix = data.plural_suffix or "" local plural_passive_suffix = data.plural_passive_suffix or "" local active_suffix_no_links = m_links.remove_links(active_suffix) local passive_suffix_no_links = m_links.remove_links(passive_suffix) local plural_suffix_no_links = m_links.remove_links(plural_suffix) local plural_passive_suffix_no_links = m_links.remove_links(plural_passive_suffix)

for slot in iter_slots(false, true) do		if not slot:find("ger_") then local prefix, suffix, prefix_no_links, suffix_no_links if slot:find("pasv") and slot:find("[123]p") then prefix = plural_passive_prefix suffix = plural_passive_suffix prefix_no_links = plural_passive_prefix_no_links suffix_no_links = plural_passive_suffix_no_links elseif slot:find("pasv") and not slot:find("_inf") then prefix = passive_prefix suffix = passive_suffix prefix_no_links = passive_prefix_no_links suffix_no_links = passive_suffix_no_links elseif slot:find("[123]p") then prefix = plural_prefix suffix = plural_suffix prefix_no_links = plural_prefix_no_links suffix_no_links = plural_suffix_no_links else prefix = active_prefix suffix = active_suffix prefix_no_links = active_prefix_no_links suffix_no_links = active_suffix_no_links end local forms = data.forms[slot] if not form_is_empty(forms) then local affixed_forms = {} if type(forms) ~= "table" then forms = {forms} end for _, form in ipairs(forms) do					if form_is_empty(form) then table.insert(affixed_forms, form) elseif slot:find("^linked") then -- If we're dealing with a linked slot, include the original links -- in the prefix/suffix and also add a link around the form itself -- if links aren't already present. (Note, above we early-exited						-- if there was no prefix and no suffix.) if not form:find("[%[%]]") then form = "" .. form .. "" end table.insert(affixed_forms, prefix .. form .. suffix) elseif form:find("[%[%]]") then -- If not dealing with a linked slot, but there are links in the slot, -- include the original, potentially linked versions of the prefix and -- suffix (e.g. in perfect passive forms). table.insert(affixed_forms, prefix .. form .. suffix) else -- Otherwise, use the non-linking versions of the prefix and suffix -- so that the whole term (including prefix/suffix) gets linked. table.insert(affixed_forms, prefix_no_links .. form .. suffix_no_links) end end data.forms[slot] = affixed_forms end end end end

local function notes_override(data, args) local notes = {args["note1"], args["note2"], args["note3"]} for n, note in pairs(notes) do		if note == "-" then data.footnotes[n] = nil elseif note == "p3inf" then data.footnotes[n] = "The present passive infinitive in -ier is a rare poetic form which is attested." elseif note == "poetsyncperf" then data.footnotes[n] = "At least one rare poetic syncopated perfect form is attested." elseif note == "sigm" then data.footnotes[n] = "At least one use of the archaic \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by Old Latin writers; most notably Plautus and Terence. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\")." elseif note == "sigmpasv" then data.footnotes[n] = "At least one use of the archaic \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by Old Latin writers; most notably Plautus and Terence. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\"). It is also attested as having a rare sigmatic future passive indicative form (\"will have been\")." elseif note == "sigmdepon" then data.footnotes[n] = "At least one use of the archaic \"sigmatic future\" tense is attested, which is used by Old Latin writers; most notably Plautus and Terence. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense." elseif note then data.footnotes[n] = note end end if args["notes"] == "-" then data.footnotes = {} end end

local function set_linked_forms(data, typeinfo) -- Generate linked variants of slots that may be the lemma. -- If the form is the same as the lemma (with links removed), -- substitute the original lemma (with links included). for _, slot in ipairs(potential_lemma_slots) do		local forms = data.forms[slot] local linked_forms = {} if forms then if type(forms) ~= "table" then forms = {forms} end for _, form in ipairs(forms) do				if form == typeinfo.lemma then table.insert(linked_forms, typeinfo.orig_lemma) else table.insert(linked_forms, form) end end end data.forms["linked_" .. slot] = linked_forms end end

function export.make_data(parent_args, from_headword, def1, def2) local params = { [1] = {required = true, default = def1 or "1+"}, [2] = {required = true, default = def2 or "amō"}, [3] = {},		[4] = {},		[5] = {},		prefix = {}, passive_prefix = {}, plural_prefix = {}, plural_passive_prefix = {}, gen_prefix = {}, dat_prefix = {}, acc_prefix = {}, abl_prefix = {}, suffix = {}, passive_suffix = {}, plural_suffix = {}, plural_passive_suffix = {}, gen_suffix = {}, dat_suffix = {}, acc_suffix = {}, abl_suffix = {}, label = {}, note1= {}, note2= {}, note3= {}, notes= {}, -- examined directly in export.show search = {} }	for slot in iter_slots(true, false) do		params[slot] = {} end

if from_headword then params.lemma = {list = true} params.id = {} params.cat = {list = true} end

local args = m_para.process(parent_args, params) local conj_type, conj_subtype, subtypes, orig_lemma, lemma = detect_decl_and_subtypes(args)

if not conjugations[conj_type] then error("Unknown conjugation type '" .. conj_type .. "'") end

local data = { forms = {}, title = {}, categories = args.cat and ut.clone(args.cat) or {}, form_footnote_indices = {}, footnotes = {}, id = args.id, overriding_lemma = args.lemma, } --note: the addition of red superscripted footnotes ('' ... ) is only implemented for the three form printing loops in which it is used local typeinfo = { lemma = lemma, orig_lemma = orig_lemma, conj_type = conj_type, conj_subtype = conj_subtype, subtypes = subtypes, }

if args.passive_prefix and not args.prefix then error("Can't specify passive_prefix= without prefix=") end if args.plural_prefix and not args.prefix then error("Can't specify plural_prefix= without prefix=") end if args.plural_passive_prefix and not args.prefix then error("Can't specify plural_passive_prefix= without prefix=") end

if args.passive_suffix and not args.suffix then error("Can't specify passive_suffix= without suffix=") end if args.plural_suffix and not args.suffix then error("Can't specify plural_suffix= without suffix=") end if args.plural_passive_suffix and not args.suffix then error("Can't specify plural_passive_suffix= without suffix=") end

local function normalize_prefix(prefix) if not prefix then return nil end local no_space_prefix = match(prefix, "(.*)_$") if no_space_prefix then return no_space_prefix elseif find(prefix, "%-$") then return prefix else return prefix .. " "		end end

local function normalize_suffix(suffix) if not suffix then return nil end local no_space_suffix = match(suffix, "^_(.*)$") if no_space_suffix then return no_space_suffix elseif find(suffix, "^%-") then return suffix else return " " .. suffix end end

data.prefix = normalize_prefix(args.prefix) data.passive_prefix = normalize_prefix(args.passive_prefix) or data.prefix data.plural_prefix = normalize_prefix(args.plural_prefix) or data.prefix -- First fall back to the passive prefix (e.g. poenās dare, where the	-- plural noun is used with both singular and plural verbs, but there's a	-- separate passive form poenae datur), then to the plural prefix, -- then to the base prefix. data.plural_passive_prefix = normalize_prefix(args.plural_passive_prefix) or		normalize_prefix(args.passive_prefix) or data.plural_prefix data.gen_prefix = normalize_prefix(args.gen_prefix) data.dat_prefix = normalize_prefix(args.dat_prefix) data.acc_prefix = normalize_prefix(args.acc_prefix) data.abl_prefix = normalize_prefix(args.abl_prefix)

data.suffix = normalize_suffix(args.suffix) data.passive_suffix = normalize_suffix(args.passive_suffix) or data.suffix data.plural_suffix = normalize_suffix(args.plural_suffix) or data.suffix -- Same as above for prefixes. data.plural_passive_suffix = normalize_suffix(args.plural_passive_suffix) or		normalize_suffix(args.passive_suffix) or data.plural_suffix data.gen_suffix = normalize_suffix(args.gen_suffix) data.dat_suffix = normalize_suffix(args.dat_suffix) data.acc_suffix = normalize_suffix(args.acc_suffix) data.abl_suffix = normalize_suffix(args.abl_suffix)

-- Generate the verb forms conjugations[conj_type](args, data, typeinfo)

-- Post-process the forms postprocess(data, typeinfo)

-- Override with user-set forms override(data, args)

-- Set linked_* forms set_linked_forms(data, typeinfo)

-- Prepend any prefixes, append any suffixes add_prefix_suffix(data) if args["label"] then ut.insert_if_not(data.title, args["label"]) end notes_override(data, args)

-- Check if the verb is irregular if not conj_type == 'irreg' then checkirregular(args, data) end return data, typeinfo end

local function form_contains(forms, form) if type(forms) == "string" then return forms == form else return ut.contains(forms, form) end end

-- Add a value to a given form key, e.g. "1s_pres_actv_indc". If the -- value is already present in the key, it won't be added again. -- -- The value is formed by concatenating STEM and SUF. SUF can be a list, -- in which case STEM will be concatenated in turn to each value in the -- list and all the resulting forms added to the key. -- -- POS is the position to insert the form(s) at; default is at the end. -- To insert at the beginning specify 1 for POS. local function add_form(data, key, stem, suf, pos) if not suf then return end if type(suf) ~= "table" then suf = {suf} end for _, s in ipairs(suf) do		if not data.forms[key] then data.forms[key] = {} elseif type(data.forms[key]) == "string" then data.forms[key] = {data.forms[key]} end ut.insert_if_not(data.forms[key], stem .. s, pos) end end

-- Add a value to all persons/numbers of a given tense/voice/mood, e.g. -- "pres_actv_indc" (specified by KEYTYPE). If a value is already present -- in a key, it won't be added again. -- -- The value for a given person/number combination is formed by concatenating -- STEM and the appropriate suffix for that person/number, e.g. SUF1S. The -- suffix can be a list, in which case STEM will be concatenated in turn to -- each value in the list and all the resulting forms added to the key. To -- not add a value for a specific person/number, specify nil or {} for the -- suffix for the person/number. local function add_forms(data, keytype, stem, suf1s, suf2s, suf3s, suf1p, suf2p, suf3p) add_form(data, "1s_" .. keytype, stem, suf1s) add_form(data, "2s_" .. keytype, stem, suf2s) add_form(data, "3s_" .. keytype, stem, suf3s) add_form(data, "1p_" .. keytype, stem, suf1p) add_form(data, "2p_" .. keytype, stem, suf2p) add_form(data, "3p_" .. keytype, stem, suf3p) end

-- Add a value to the 2nd person (singular and plural) of a given -- tense/voice/mood. This works like add_forms. local function add_2_forms(data, keytype, stem, suf2s, suf2p) add_form(data, "2s_" .. keytype, stem, suf2s) add_form(data, "2p_" .. keytype, stem, suf2p) end

-- Add a value to the 2nd and 3rd persons (singular and plural) of a given -- tense/voice/mood. This works like add_forms. local function add_23_forms(data, keytype, stem, suf2s, suf3s, suf2p, suf3p) add_form(data, "2s_" .. keytype, stem, suf2s) add_form(data, "3s_" .. keytype, stem, suf3s) add_form(data, "2p_" .. keytype, stem, suf2p) add_form(data, "3p_" .. keytype, stem, suf3p) end

-- Clear out all forms from a given key (e.g. "1s_pres_actv_indc"). local function clear_form(data, key) data.forms[key] = nil end

-- Clear out all forms from all persons/numbers a given tense/voice/mood -- (e.g. "pres_actv_indc"). local function clear_forms(data, keytype) clear_form(data, "1s_" .. keytype) clear_form(data, "2s_" .. keytype) clear_form(data, "3s_" .. keytype) clear_form(data, "1p_" .. keytype) clear_form(data, "2p_" .. keytype) clear_form(data, "3p_" .. keytype) end

local function make_perfect_passive(data) local ppp = data.forms["perf_pasv_ptc"] if type(ppp) ~= "table" then ppp = {ppp} end local ppplinks = {} for _, pppform in ipairs(ppp) do		table.insert(ppplinks, make_link({lang = lang, term = pppform}, "term")) end local ppplink = table.concat(ppplinks, " or ") local sumlink = make_link({lang = lang, term = "sum"}, "term")

text_for_slot = { perf_pasv_indc = "present active indicative", futp_pasv_indc = "future active indicative", plup_pasv_indc = "imperfect active indicative", perf_pasv_subj = "present active subjunctive", plup_pasv_subj = "imperfect active subjunctive" }	local prefix_joiner = data.passive_prefix and data.passive_prefix:find(" $") and "+ " or "" local suffix_joiner = data.passive_suffix and data.passive_suffix:find("^ ") and " +" or "" for slot, text in pairs(text_for_slot) do		data.forms[slot] = (data.passive_prefix or "") .. prefix_joiner .. ppplink .. " + " ..			text .. " of " .. sumlink .. suffix_joiner .. (data.passive_suffix or "") end ppp = data.forms["1s_pres_actv_indc"] if type(ppp) ~= "table" then ppp = {ppp} end if ppp[1] == "faciō" then ppp = {"factum"} ppplinks = {} for _, pppform in ipairs(ppp) do			table.insert(ppplinks, make_link({lang = lang, term = pppform}, "term")) end ppplink = table.concat(ppplinks, " or ") sumlink = make_link({lang = lang, term = "sum"}, "term") for slot, text in pairs(text_for_slot) do			data.forms[slot] = data.forms[slot] .. " or " .. ppplink .. " + " .. text .. " of " .. sumlink end end end

-- Make the gerund and gerundive/future passive participle. For the forms -- labeled "gerund", we generate both gerund and gerundive variants if there's -- a case-specific prefix or suffix for the case in question; otherwise we -- generate only the gerund per se. BASE is the stem (ending in -nd). -- UND_VARIANT, if true, means that a gerundive in -und should be generated -- along with a gerundive in -end. NO_GERUND means to skip generating any -- gerunds (and gerundive variants). NO_FUTR_PASV_PTC means to skip generating -- the future passive participle. local function make_gerund(data, typeinfo, base, und_variant, no_gerund, no_futr_pasv_ptc) local neut_endings = { nom = "um", gen = "ī", dat = "ō", acc = "um", abl = "ō", }

local endings if typeinfo.subtypes.f then endings = { nom = "a", gen = "ae", dat = "ae", acc = "am", abl = "ā", }	elseif typeinfo.subtypes.n then endings = neut_endings elseif typeinfo.subtypes.mp then endings = { nom = "ī", gen = "ōrum", dat = "īs", acc = "ōs", abl = "īs", }	elseif typeinfo.subtypes.fp then endings = { nom = "ae", gen = "ārum", dat = "īs", acc = "ās", abl = "īs", }	elseif typeinfo.subtypes.np then endings = { nom = "a", gen = "ōrum", dat = "īs", acc = "a", abl = "īs", }	else endings = { nom = "us", gen = "ī", dat = "ō", acc = "um", abl = "ō", }	end

if find(base, "[uv]end$") or typeinfo.subtypes.nound then -- Per Lane's grammar section 899: "Verbs in -ere and -īre often have		-- -undus, when not preceded by u or v, especially in formal style" -- There is also an optional exclusion if -undus is not attested und_variant = false end local und_base = und_variant and base:gsub("end$", "und") for case, ending in pairs(endings) do		if case == "nom" then if not no_futr_pasv_ptc then if typeinfo.subtypes.passimpers then ending = "um" end add_form(data, "futr_pasv_ptc", "", base .. ending) if und_base then add_form(data, "futr_pasv_ptc", "", und_base .. ending) end end elseif (data[case .. "_prefix"] or data[case .. "_suffix"]) and not no_gerund then add_form(data, "ger_" .. case, "", (data[case .. "_prefix"] or "")				.. base .. ending .. (data[case .. "_suffix"] or "")) if und_base then add_form(data, "ger_" .. case, "", (data[case .. "_prefix"] or "")					.. und_base .. ending .. (data[case .. "_suffix"] or "")) end end end if not no_gerund then for case, ending in pairs(neut_endings) do add_form(data, "ger_" .. case, "",				(data.prefix or "") ..	base .. ending .. (data.suffix or  "")) end end end

postprocess = function(data, typeinfo) -- Maybe clear out the supine-derived forms (except maybe for the	-- future active participle). Do this first because some code below -- looks at the perfect participle to derive other forms. if typeinfo.subtypes.nosup then -- Some verbs have no supine forms or forms derived from the supine if typeinfo.subtypes.perfaspres == nil then ut.insert_if_not(data.title, "no supine stem") end ut.insert_if_not(data.categories, "Latin verbs with missing supine stem") ut.insert_if_not(data.categories, "Latin defective verbs")

for key, _ in pairs(data.forms) do			if cfind(key, "sup") or (				key == "perf_actv_ptc" or key == "perf_pasv_ptc" or key == "perf_pasv_inf" or				key == "futr_actv_ptc" or key == "futr_actv_inf" or key == "futr_pasv_inf" or				(typeinfo.subtypes.depon or typeinfo.subtypes.semidepon or				 typeinfo.subtypes.optsemidepon) and key == "perf_actv_inf"			) then data.forms[key] = nil end end elseif typeinfo.subtypes.supfutractvonly then -- Some verbs have no supine forms or forms derived from the supine, -- except for the future active infinitive/participle if typeinfo.subtypes.perfaspres == nil then ut.insert_if_not(data.title, "no supine stem except in the future active participle") end ut.insert_if_not(data.categories, "Latin verbs with missing supine stem except in the future active participle") ut.insert_if_not(data.categories, "Latin defective verbs")

for key, _ in pairs(data.forms) do			if cfind(key, "sup") or (				key == "perf_actv_ptc" or key == "perf_pasv_ptc" or key == "perf_pasv_inf" or				key == "futr_pasv_inf"			) then data.forms[key] = nil end end end -- Add information for the passive perfective forms if data.forms["perf_pasv_ptc"] and not form_is_empty(data.forms["perf_pasv_ptc"]) then if typeinfo.subtypes.passimpers then -- this should always be a table because it's generated only in			-- make_supine local pppforms = data.forms["perf_pasv_ptc"] for _, ppp in ipairs(pppforms) do				if not form_is_empty(ppp) then -- make_supine already generated the neuter form of the PPP. local nns_ppp = make_raw_link(ppp) add_form(data, "3s_perf_pasv_indc", nns_ppp, " est") add_form(data, "3s_futp_pasv_indc", nns_ppp, " erit") add_form(data, "3s_plup_pasv_indc", nns_ppp, " erat") add_form(data, "3s_perf_pasv_subj", nns_ppp, " sit") add_form(data, "3s_plup_pasv_subj", nns_ppp, {" esset", " foret"}) end end elseif typeinfo.subtypes.pass3only then local pppforms = data.forms["perf_pasv_ptc"] if type(pppforms) ~= "table" then pppforms = {pppforms} end for _, ppp in ipairs(pppforms) do				if not form_is_empty(ppp) then local ppp_s, ppp_p if typeinfo.subtypes.mp then ppp_p = make_raw_link(gsub1(ppp, "ī$", "us"), ppp) elseif typeinfo.subtypes.fp then ppp_p = make_raw_link(gsub1(ppp, "ae$", "us"), ppp) elseif typeinfo.subtypes.np then ppp_p = make_raw_link(gsub1(ppp, "a$", "us"), ppp) elseif typeinfo.subtypes.f then local ppp_lemma = gsub1(ppp, "a$", "us") ppp_s = make_raw_link(ppp_lemma, ppp) ppp_p = make_raw_link(ppp_lemma, gsub1(ppp, "a$", "ae")) elseif typeinfo.subtypes.n then local ppp_lemma = gsub1(ppp, "um$", "us") ppp_s = make_raw_link(ppp_lemma, ppp) ppp_p = make_raw_link(ppp_lemma, gsub1(ppp, "um$", "a")) else ppp_s = make_raw_link(ppp) ppp_p = make_raw_link(ppp, gsub1(ppp, "us$", "ī")) end if not typeinfo.subtypes.mp and not typeinfo.subtypes.fp and not typeinfo.subtypes.np then add_form(data, "3s_perf_pasv_indc", ppp_s, " est") add_form(data, "3s_futp_pasv_indc", ppp_s, " erit") add_form(data, "3s_plup_pasv_indc", ppp_s, " erat") add_form(data, "3s_perf_pasv_subj", ppp_s, " sit") add_form(data, "3s_plup_pasv_subj", ppp_s, {" esset", " foret"}) end add_form(data, "3p_perf_pasv_indc", ppp_p, " sunt") add_form(data, "3p_futp_pasv_indc", ppp_p, " erunt") add_form(data, "3p_plup_pasv_indc", ppp_p, " erant") add_form(data, "3p_perf_pasv_subj", ppp_p, " sint") add_form(data, "3p_plup_pasv_subj", ppp_p, {" essent", " forent"}) end end else make_perfect_passive(data) end end

if typeinfo.subtypes.perfaspres then -- Perfect forms as present tense ut.insert_if_not(data.title, "no present stem") if typeinfo.subtypes.nosup then ut.insert_if_not(data.title, "no supine stem") elseif typeinfo.subtypes.supfutractvonly then ut.insert_if_not(data.title, "no supine stem except in the future active participle") end ut.insert_if_not(data.title, "active only") ut.insert_if_not(data.title, "perfect forms as present") ut.insert_if_not(data.title, "pluperfect as imperfect") ut.insert_if_not(data.title, "future perfect as future") ut.insert_if_not(data.categories, "Latin defective verbs") ut.insert_if_not(data.categories, "Latin active-only verbs") ut.insert_if_not(data.categories, "Latin verbs with missing present stem") ut.insert_if_not(data.categories, "Latin verbs with perfect forms having imperfective meanings")

-- Change perfect passive participle to perfect active participle data.forms["perf_actv_ptc"] = data.forms["perf_pasv_ptc"]

-- Change perfect active infinitive to present active infinitive data.forms["pres_actv_inf"] = data.forms["perf_actv_inf"]

-- Remove passive forms -- Remove present active, imperfect active and future active forms for key, _ in pairs(data.forms) do			if key ~= "futr_actv_inf" and key ~= "futr_actv_ptc" and (				cfind(key, "pasv") or cfind(key, "pres") and key ~= "pres_actv_inf" or				cfind(key, "impf") or cfind(key, "futr")			) then data.forms[key] = nil end end

-- Change perfect forms to non-perfect forms for key, form in pairs(data.forms) do			if cfind(key, "perf") and key ~= "perf_actv_ptc" then data.forms[key:gsub("perf", "pres")] = form data.forms[key] = nil elseif cfind(key, "plup") then data.forms[key:gsub("plup", "impf")] = form data.forms[key] = nil elseif cfind(key, "futp") then data.forms[key:gsub("futp", "futr")] = form data.forms[key] = nil elseif cfind(key, "ger") then data.forms[key] = nil end end

data.forms["pres_actv_ptc"] = nil end

-- Types of irregularity related primarily to the active. -- These could in theory be combined with those related to the passive and imperative, -- i.e. there's no reason there couldn't be an impersonal deponent verb with no imperatives. if typeinfo.subtypes.impers then -- Impersonal verbs have only third-person singular forms. ut.insert_if_not(data.title, "impersonal") ut.insert_if_not(data.categories, "Latin impersonal verbs")

-- Remove all non-3sg forms for key, _ in pairs(data.forms) do			if key:find("^[12][sp]") or key:find("^3p") then data.forms[key] = nil end end elseif typeinfo.subtypes["3only"] then ut.insert_if_not(data.title, "third person only") ut.insert_if_not(data.categories, "Latin third-person-only verbs")

-- Remove all non-3sg forms for key, _ in pairs(data.forms) do			if key:find("^[12][sp]") then data.forms[key] = nil end end end

if typeinfo.subtypes.nopasvperf and not typeinfo.subtypes.nosup and not typeinfo.subtypes.supfutractvonly then -- Some verbs have no passive perfect forms (e.g. ārēscō, -ěre). -- Only do anything here if the verb has a supine; otherwise it -- necessarily has no passive perfect forms. ut.insert_if_not(data.title, "no passive perfect forms") ut.insert_if_not(data.categories, "Latin defective verbs")

-- Remove all passive perfect forms for key, _ in pairs(data.forms) do			if cfind(key, "pasv") and (cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp")) then data.forms[key] = nil end end end

-- Handle certain irregularities in the passive if typeinfo.subtypes.optsemidepon then -- Optional semi-deponent verbs use perfective passive forms with active -- meaning, but also have perfect active forms with the same meaning, -- and have no imperfective passive. We already generated the perfective -- forms but need to clear out the imperfective passive. ut.insert_if_not(data.title, "optionally semi-deponent") ut.insert_if_not(data.categories, "Latin semi-deponent verbs") ut.insert_if_not(data.categories, "Latin optionally semi-deponent verbs")

-- Remove imperfective passive forms for key, _ in pairs(data.forms) do			if cfind(key, "pres_pasv") or cfind(key, "impf_pasv") or cfind(key, "futr_pasv") then data.forms[key] = nil end end elseif typeinfo.subtypes.semidepon then -- Semi-deponent verbs use perfective passive forms with active meaning, -- and have no imperfective passive ut.insert_if_not(data.title, "semi-deponent") ut.insert_if_not(data.categories, "Latin semi-deponent verbs")

-- Remove perfective active and imperfective passive forms for key, _ in pairs(data.forms) do			if cfind(key, "perf_actv") or cfind(key, "plup_actv") or cfind(key, "futp_actv") or cfind(key, "pres_pasv") or cfind(key, "impf_pasv") or cfind(key, "futr_pasv") then data.forms[key] = nil end end

-- Change perfective passive to active for key, form in pairs(data.forms) do			if cfind(key, "perf_pasv") or cfind(key, "plup_pasv") or cfind(key, "futp_pasv") then data.forms[key:gsub("pasv", "actv")] = form data.forms[key] = nil end end elseif typeinfo.subtypes.depon then -- Deponent verbs use passive forms with active meaning ut.insert_if_not(data.title, "deponent") ut.insert_if_not(data.categories, "Latin deponent verbs")

-- Remove active forms and future passive infinitive for key, _ in pairs(data.forms) do			if cfind(key, "actv") and key ~= "pres_actv_ptc" and key ~= "futr_actv_ptc" and key ~= "futr_actv_inf" and cfind(key, "sigf") == nil or key == "futr_pasv_inf" then data.forms[key] = nil end end

-- Change passive to active for key, form in pairs(data.forms) do			if cfind(key, "pasv") and key ~= "pres_pasv_ptc" and key ~= "futr_pasv_ptc" and key ~= "futr_pasv_inf" then data.forms[key:gsub("pasv", "actv")] = form data.forms[key] = nil end end end

if typeinfo.subtypes.noperf then -- Some verbs have no perfect stem (e.g. inalbēscō, -ěre) ut.insert_if_not(data.title, "no perfect stem") ut.insert_if_not(data.categories, "Latin verbs with missing perfect stem") ut.insert_if_not(data.categories, "Latin defective verbs")

-- Remove all active perfect forms (passive perfect forms may		-- still exist as they are formed with the supine stem) for key, _ in pairs(data.forms) do			if cfind(key, "actv") and (cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp")) then data.forms[key] = nil end end end

if typeinfo.subtypes.nopass then -- Remove all passive forms ut.insert_if_not(data.title, "active only") ut.insert_if_not(data.categories, "Latin active-only verbs")

-- Remove all non-3sg and passive forms for key, _ in pairs(data.forms) do			if cfind(key, "pasv") then data.forms[key] = nil end end elseif typeinfo.subtypes.pass3only then -- Some verbs have only third-person forms in the passive ut.insert_if_not(data.title, "only third-person forms in passive") ut.insert_if_not(data.categories, "Latin verbs with third-person passive")

-- Remove all non-3rd-person passive forms and all passive imperatives for key, _ in pairs(data.forms) do			if cfind(key, "pasv") and (key:find("^[12][sp]") or cfind(key, "impr")) then data.forms[key] = nil end -- For phrasal verbs with a plural complement, also need to erase the -- 3s forms. if typeinfo.subtypes.mp or typeinfo.subtypes.fp or typeinfo.subtypes.np then if cfind(key, "pasv") and key:find("^3s") then data.forms[key] = nil end end end elseif typeinfo.subtypes.passimpers then -- Some verbs are impersonal in the passive ut.insert_if_not(data.title, "impersonal in passive") ut.insert_if_not(data.categories, "Latin verbs with impersonal passive")

-- Remove all non-3sg passive forms for key, _ in pairs(data.forms) do			if cfind(key, "pasv") and (key:find("^[12][sp]") or key:find("^3p") or cfind(key, "impr")) or cfind(key, "futr_pasv_inf") then data.forms[key] = nil end end end

-- Handle certain irregularities in the imperative if typeinfo.subtypes.noimp then -- Some verbs have no imperatives ut.insert_if_not(data.title, "no imperatives") ut.insert_if_not(data.categories, "Latin verbs with missing imperative") ut.insert_if_not(data.categories, "Latin defective verbs")

-- Remove all imperative forms for key, _ in pairs(data.forms) do			if cfind(key, "impr") then data.forms[key] = nil end end end

-- Handle certain irregularities in the future if typeinfo.subtypes.nofut then -- Some verbs (e.g. soleō) have no future ut.insert_if_not(data.title, "no future") ut.insert_if_not(data.categories, "Latin verbs with missing future") ut.insert_if_not(data.categories, "Latin defective verbs")

-- Remove all future forms for key, _ in pairs(data.forms) do			if cfind(key, "fut") then -- handles futr = future and futp = future perfect data.forms[key] = nil end end end

-- Add the ancient future_passive_participle of certain verbs -- if typeinfo.pres_stem == "lāb" then -- 	data.forms["futr_pasv_ptc"] = "lābundus" -- elseif typeinfo.pres_stem == "collāb" then -- 	data.forms["futr_pasv_ptc"] = "collābundus" -- elseif typeinfo.pres_stem == "illāb" then -- 	data.forms["futr_pasv_ptc"] = "illābundus" -- elseif typeinfo.pres_stem == "relāb" then -- 	data.forms["futr_pasv_ptc"] = "relābundus" -- end

-- Add the poetic present passive infinitive forms of certain verbs if typeinfo.subtypes.p3inf then local is_depon = typeinfo.subtypes.depon local form = "pres_" .. (is_depon and "actv" or "pasv") .. "_inf" local noteindex = #(data.footnotes) + 1 local formval = data.forms[form] if type(formval) ~= "table" then formval = {formval} end local newvals = mw.clone(formval) for _, fv in ipairs(formval) do table.insert(newvals, sub(fv, 1, -2) .. "ier") end data.forms[form] = newvals data.form_footnote_indices[form] = tostring(noteindex) data.footnotes[noteindex] = 'The present passive infinitive in -ier is a rare poetic form which is attested.' end

--Add the syncopated perfect forms, omitting the separately handled fourth conjugation cases

if typeinfo.subtypes.poetsyncperf then local sss = { --infinitive {'perf_actv_inf', 'sse'}, --unambiguous perfect actives {'2s_perf_actv_indc', 'stī'}, {'2p_perf_actv_indc', 'stis'}, --pluperfect subjunctives {'1s_plup_actv_subj', 'ssem'}, {'2s_plup_actv_subj', 'ssēs'}, {'3s_plup_actv_subj', 'sset'}, {'1p_plup_actv_subj', 'ssēmus'}, {'2p_plup_actv_subj', 'ssētis'}, {'3p_plup_actv_subj', 'ssent'} }		local noteindex = #(data.footnotes)+1 function add_sync_perf(form, suff_sync) local formval = data.forms[form] if type(formval) ~= "table" then formval = {formval} end local newvals = mw.clone(formval) for _, fv in ipairs(formval) do				-- Can only syncopate 'vi', or 'vi' spelled as 'ui' after a vowel if fv:find('vi' .. suff_sync .. '$') or find(fv, '[aeiouyāēīōūȳăĕĭŏŭ]ui' .. suff_sync.. '$') then ut.insert_if_not(newvals, sub(fv, 1, -len(suff_sync) - 3) .. suff_sync) end end data.forms[form] = newvals data.form_footnote_indices[form] = noteindex end for _, v in ipairs(sss) do			add_sync_perf(v[1], v[2]) end data.footnotes[noteindex] = "At least one rare poetic syncopated perfect form is attested." end -- Add category for sigmatic forms if typeinfo.subtypes.sigm or typeinfo.subtypes.sigmpasv then ut.insert_if_not(data.categories, "Latin verbs with sigmatic forms") end -- Add subcategory for passive sigmatic forms if typeinfo.subtypes.sigmpasv or (typeinfo.subtypes.sigm and typeinfo.subtypes.depon) then ut.insert_if_not(data.categories, "Latin verbs with passive sigmatic forms") end

end

--[=[	Conjugation functions ]=]--

local function get_regular_stems(args, typeinfo) -- Get the parameters if typeinfo.subtypes.depon or typeinfo.subtypes.semidepon then -- Deponent and semi-deponent verbs don't have the perfective principal part. -- But optionally semi-deponent verbs do. typeinfo.pres_stem = ine(args[1]) typeinfo.perf_stem = nil typeinfo.supine_stem = ine(args[2]) elseif typeinfo.subtypes.perfaspres then typeinfo.perf_stem = ine(args[1]) typeinfo.supine_stem = ine(args[2]) else typeinfo.pres_stem = ine(args[1]) typeinfo.perf_stem = ine(args[2]) typeinfo.supine_stem = ine(args[3]) end if typeinfo.subtypes.sigm or typeinfo.subtypes.sigmpasv then typeinfo.sigm_stem = ine(args[5]) end

-- Prepare stems if not typeinfo.pres_stem then if NAMESPACE == "Template" or typeinfo.subtypes.perfaspres then typeinfo.pres_stem = "-" else error("Present stem has not been provided") end end

if typeinfo.perf_stem then typeinfo.perf_stem = split(typeinfo.perf_stem, "/") else typeinfo.perf_stem = {} end

if typeinfo.supine_stem then typeinfo.supine_stem = split(typeinfo.supine_stem, "/") else typeinfo.supine_stem = {} end if typeinfo.sigm_stem then typeinfo.sigm_stem = split(typeinfo.sigm_stem, "/") else typeinfo.sigm_stem = {} end end

local function has_perf_in_s_or_x(pres_stem, perf_stem) if pres_stem == perf_stem then return false end

return perf_stem and perf_stem:find("[sx]$") ~= nil end

conjugations["1st"] = function(args, data, typeinfo) get_regular_stems(args, typeinfo)

table.insert(data.title, "first conjugation") table.insert(data.categories, "Latin first conjugation verbs")

for _, perf_stem in ipairs(typeinfo.perf_stem) do if perf_stem == typeinfo.pres_stem .. "āv" then table.insert(data.categories, "Latin first conjugation verbs with perfect in -av-") elseif perf_stem == typeinfo.pres_stem .. "u" then table.insert(data.categories, "Latin first conjugation verbs with perfect in -u-") elseif perf_stem == typeinfo.pres_stem then table.insert(data.categories, "Latin first conjugation verbs with suffixless perfect") else table.insert(data.categories, "Latin first conjugation verbs with irregular perfect") end end

make_pres_1st(data, typeinfo, typeinfo.pres_stem) make_perf_and_supine(data, typeinfo) make_sigm(data, typeinfo, typeinfo.sigm_stem) --Additional forms in specific cases if typeinfo.pres_stem == "dīlapid" then add_form(data, "3p_sigf_actv_indc", "", "dīlapidāssunt", 2 ) elseif typeinfo.pres_stem == "invol" then add_form(data, "3s_sigf_actv_indc", "", "involāsit", 2 ) elseif typeinfo.pres_stem == "viol" then local noteindex = #(data.footnotes) + 1 add_form(data, "3p_futp_actv_indc", "", "violārint", 2 ) add_form(data, "3p_perf_actv_subj", "", "violārint", 2 ) add_form(data, "3s_sigf_actv_indc", "", "violāsit", 2 ) data.form_footnote_indices["3p_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3p_perf_actv_subj"] = tostring(noteindex) data.footnotes[noteindex] = 'Archaic.' end end

conjugations["2nd"] = function(args, data, typeinfo) get_regular_stems(args, typeinfo)

table.insert(data.title, "second conjugation") table.insert(data.categories, "Latin second conjugation verbs")

for _, perf_stem in ipairs(typeinfo.perf_stem) do		local pres_stem = typeinfo.pres_stem pres_stem = pres_stem:gsub("qu", "1") perf_stem = perf_stem:gsub("qu", "1") if perf_stem == pres_stem .. "ēv" then table.insert(data.categories, "Latin second conjugation verbs with perfect in -ev-") elseif perf_stem == pres_stem .. "u" then table.insert(data.categories, "Latin second conjugation verbs with perfect in -u-") elseif perf_stem == pres_stem then table.insert(data.categories, "Latin second conjugation verbs with suffixless perfect") elseif has_perf_in_s_or_x(pres_stem, perf_stem) then table.insert(data.categories, "Latin second conjugation verbs with perfect in -s- or -x-") else table.insert(data.categories, "Latin second conjugation verbs with irregular perfect") end end

make_pres_2nd(data, typeinfo, typeinfo.pres_stem) make_perf_and_supine(data, typeinfo) make_sigm(data, typeinfo, typeinfo.sigm_stem) --Additional forms in specific cases if typeinfo.pres_stem == "noc" then add_form(data, "3s_siga_actv_subj", "", "noxsīt", 2 ) end end

local function set_3rd_conj_categories(data, typeinfo) table.insert(data.categories, "Latin third conjugation verbs")

for _, perf_stem in ipairs(typeinfo.perf_stem) do		local pres_stem = typeinfo.pres_stem pres_stem = pres_stem:gsub("qu", "1") perf_stem = perf_stem:gsub("qu", "1") if perf_stem == pres_stem .. "āv" then table.insert(data.categories, "Latin third conjugation verbs with perfect in -av-") elseif perf_stem == pres_stem .. "ēv" then table.insert(data.categories, "Latin third conjugation verbs with perfect in -ev-") elseif perf_stem == pres_stem .. "īv" then table.insert(data.categories, "Latin third conjugation verbs with perfect in -iv-") elseif perf_stem == pres_stem .. "i" then table.insert(data.categories, "Latin third conjugation verbs with perfect in -i-") elseif perf_stem == pres_stem .. "u" then table.insert(data.categories, "Latin third conjugation verbs with perfect in -u-") elseif perf_stem == pres_stem then table.insert(data.categories, "Latin third conjugation verbs with suffixless perfect") elseif has_perf_in_s_or_x(pres_stem, perf_stem) then table.insert(data.categories, "Latin third conjugation verbs with perfect in -s- or -x-") else table.insert(data.categories, "Latin third conjugation verbs with irregular perfect") end end end

conjugations["3rd"] = function(args, data, typeinfo) get_regular_stems(args, typeinfo)

table.insert(data.title, "third conjugation") set_3rd_conj_categories(data, typeinfo)

if typeinfo.pres_stem and match(typeinfo.pres_stem,"[āēīōū]sc$") then table.insert(data.categories, "Latin inchoative verbs") end

make_pres_3rd(data, typeinfo, typeinfo.pres_stem) make_perf_and_supine(data, typeinfo) make_sigm(data, typeinfo, typeinfo.sigm_stem) --Additional forms in specific cases --FIXME: needs to be cleared up	if match(typeinfo.pres_stem, "nōsc") then local noteindex = #(data.footnotes) + 1 add_form(data, "2s_perf_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "stī", 2 ) add_form(data, "1p_perf_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "mus", 2 ) add_form(data, "2p_perf_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "stis", 2 ) add_form(data, "3p_perf_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "runt", 3 ) add_form(data, "1s_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "ram", 2 ) add_form(data, "2s_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rās", 2 ) add_form(data, "3s_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rat", 2 ) add_form(data, "1p_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rāmus", 2 ) add_form(data, "2p_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rātis", 2 ) add_form(data, "3p_plup_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rant", 2 ) add_form(data, "1s_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rō", 2 ) add_form(data, "2s_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "ris", 2 ) add_form(data, "3s_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rit", 2 ) add_form(data, "1p_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rimus", 2 ) add_form(data, "2p_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "ritis", 2 ) add_form(data, "3p_futp_actv_indc", "", sub(typeinfo.perf_stem[1],1,-2) .. "rint", 2 ) add_form(data, "1s_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rim", 2 ) add_form(data, "2s_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rīs", 2 ) add_form(data, "3s_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rit", 2 ) add_form(data, "1p_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rīmus", 2 ) add_form(data, "2p_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rītis", 2 ) add_form(data, "3p_perf_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "rint", 2 ) add_form(data, "1s_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "ssem", 2 ) add_form(data, "2s_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "ssēs", 2 ) add_form(data, "3s_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "sset", 2 ) add_form(data, "1p_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "ssēmus", 2 ) add_form(data, "2p_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "ssētis", 2 ) add_form(data, "3p_plup_actv_subj", "", sub(typeinfo.perf_stem[1],1,-2) .. "ssent", 2 ) add_form(data, "perf_actv_inf", "", sub(typeinfo.perf_stem[1],1,-2) .. "sse", 2 ) data.form_footnote_indices["2s_perf_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1p_perf_actv_indc"] = tostring(noteindex) data.form_footnote_indices["2p_perf_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3p_perf_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1s_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["2s_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3s_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1p_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["2p_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3p_plup_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1s_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["2s_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3s_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1p_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["2p_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3p_futp_actv_indc"] = tostring(noteindex) data.form_footnote_indices["1s_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["2s_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["3s_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["1p_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["2p_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["3p_perf_actv_subj"] = tostring(noteindex) data.form_footnote_indices["1s_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["2s_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["3s_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["1p_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["2p_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["3p_plup_actv_subj"] = tostring(noteindex) data.form_footnote_indices["perf_actv_inf"] = tostring(noteindex) data.footnotes[noteindex] = 'The verb \"nōscō\" and its compounds frequently drop the syllables \"vi\" and \"ve\" from their perfect, pluperfect and future perfect conjugations.' end if typeinfo.pres_stem == "ulcīsc" then local noteindex = #(data.footnotes) + 1 add_form(data, "1s_sigf_actv_indc", "", "ullō", 2 ) data.form_footnote_indices["1s_sigf_actv_indc"] = tostring(noteindex) data.footnotes[noteindex] = 'The form \"ullō\" may have resulted from a later, erroneous misreading of \"ulsō\".' end end

conjugations["3rd-io"] = function(args, data, typeinfo) get_regular_stems(args, typeinfo)

table.insert(data.title, "third conjugation iō-variant") set_3rd_conj_categories(data, typeinfo)

make_pres_3rd_io(data, typeinfo, typeinfo.pres_stem) make_perf_and_supine(data, typeinfo) make_sigm(data, typeinfo, typeinfo.sigm_stem) end

local function ivi_ive(form) form = form:gsub("īvī", "iī") form = form:gsub("īvi", "ī") form = form:gsub("īve", "ī") form = form:gsub("īvē", "ē") return form end

conjugations["4th"] = function(args, data, typeinfo) get_regular_stems(args, typeinfo)

table.insert(data.title, "fourth conjugation") table.insert(data.categories, "Latin fourth conjugation verbs")

for _, perf_stem in ipairs(typeinfo.perf_stem) do		local pres_stem = typeinfo.pres_stem pres_stem = pres_stem:gsub("qu", "1") perf_stem = perf_stem:gsub("qu", "1") if perf_stem == pres_stem .. "īv" then table.insert(data.categories, "Latin fourth conjugation verbs with perfect in -iv-") elseif perf_stem == pres_stem .. "i" then table.insert(data.categories, "Latin fourth conjugation verbs with perfect in -i-") elseif perf_stem == pres_stem .. "u" then table.insert(data.categories, "Latin fourth conjugation verbs with perfect in -u-") elseif perf_stem == pres_stem then table.insert(data.categories, "Latin fourth conjugation verbs with suffixless perfect") elseif has_perf_in_s_or_x(pres_stem, perf_stem) then table.insert(data.categories, "Latin fourth conjugation verbs with perfect in -s- or -x-") else table.insert(data.categories, "Latin fourth conjugation verbs with irregular perfect") end end

make_pres_4th(data, typeinfo, typeinfo.pres_stem) make_perf_and_supine(data, typeinfo) make_sigm(data, typeinfo, typeinfo.sigm_stem)

if form_contains(data.forms["1s_pres_actv_indc"], "serviō") or form_contains(data.forms["1s_pres_actv_indc"], "saeviō") then add_forms(data, "impf_actv_indc", typeinfo.pres_stem,			{"iēbam", "ībam"},			{"iēbās", "ībās"},			{"iēbat", "ībat"},			{"iēbāmus", "ībāmus"},			{"iēbātis", "ībātis"},			{"iēbant", "ībant"}		)

add_forms(data, "futr_actv_indc", typeinfo.pres_stem,			{"iam", "ībō"},			{"iēs", "ībis"},			{"iet", "ībit"},			{"iēmus", "ībimus"},			{"iētis", "ībitis"},			{"ient", "ībunt"}		) end

if typeinfo.subtypes.alwayssyncperf or typeinfo.subtypes.optsyncperf then for key, form in pairs(data.forms) do			if cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp") then local forms = data.forms[key] if type(forms) ~= "table" then forms = {forms} end data.forms[key] = {} for _, f in ipairs(forms) do					if typeinfo.subtypes.optsyncperf then ut.insert_if_not(data.forms[key], f)					end ut.insert_if_not(data.forms[key], ivi_ive(f)) end end end end end

-- Irregular conjugations local irreg_conjugations = {}

conjugations["irreg"] = function(args, data, typeinfo) local verb = ine(args[1]) local prefix = ine(args[2])

if not verb then if NAMESPACE == "Template" then verb = "sum" else error("The verb to be conjugated has not been specified.") end end

if not irreg_conjugations[verb] then error("The verb '" .. verb .. "' is not recognised as an irregular verb.") end

typeinfo.verb = verb typeinfo.prefix = prefix

-- Generate the verb forms irreg_conjugations[verb](args, data, typeinfo) end

irreg_conjugations["aio"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation iō-variant") table.insert(data.title, "irregular") table.insert(data.title, "active only") table.insert(data.title, "highly defective") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin active-only verbs") table.insert(data.categories, "Latin defective verbs")

-- Signal to to display the verb as irregular and highly defective typeinfo.subtypes.irreg = true typeinfo.subtypes.highlydef = true

local prefix = typeinfo.prefix or ""

data.forms["1s_pres_actv_indc"] = prefix .. "aiō" data.forms["2s_pres_actv_indc"] = prefix .. "ais" data.forms["3s_pres_actv_indc"] = prefix .. "ait" data.forms["3p_pres_actv_indc"] = prefix .. "aiunt"

data.forms["1s_impf_actv_indc"] = prefix .. "aiēbam" data.forms["2s_impf_actv_indc"] = prefix .. "aiēbās" data.forms["3s_impf_actv_indc"] = prefix .. "aiēbat" data.forms["1p_impf_actv_indc"] = prefix .. "aiēbāmus" data.forms["2p_impf_actv_indc"] = prefix .. "aiēbātis" data.forms["3p_impf_actv_indc"] = prefix .. "aiēbant"

data.forms["2s_perf_actv_indc"] = prefix .. "aistī" data.forms["3s_perf_actv_indc"] = prefix .. "ait"

data.forms["2s_pres_actv_subj"] = prefix .. "aiās" data.forms["3s_pres_actv_subj"] = prefix .. "aiat" data.forms["3p_pres_actv_subj"] = prefix .. "aiant"

data.forms["2s_pres_actv_impr"] = prefix .. "ai"

data.forms["pres_actv_inf"] = prefix .. "aiere" data.forms["pres_actv_ptc"] = prefix .. "aiēns" end

irreg_conjugations["aiio"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation iō-variant") table.insert(data.title, "irregular") table.insert(data.title, "active only") table.insert(data.title, "highly defective") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin active-only verbs") table.insert(data.categories, "Latin defective verbs")

-- Signal to to display the verb as irregular and highly defective typeinfo.subtypes.irreg = true typeinfo.subtypes.highlydef = true

local prefix = typeinfo.prefix or ""

data.forms["1s_pres_actv_indc"] = prefix .. "aiiō" data.forms["2s_pres_actv_indc"] = prefix .. "ais" data.forms["3s_pres_actv_indc"] = prefix .. "ait" data.forms["3p_pres_actv_indc"] = prefix .. "aiunt"

data.forms["1s_impf_actv_indc"] = prefix .. "aiiēbam" data.forms["2s_impf_actv_indc"] = prefix .. "aiiēbās" data.forms["3s_impf_actv_indc"] = prefix .. "aiiēbat" data.forms["1p_impf_actv_indc"] = prefix .. "aiiēbāmus" data.forms["2p_impf_actv_indc"] = prefix .. "aiiēbātis" data.forms["3p_impf_actv_indc"] = prefix .. "aiiēbant"

data.forms["2s_perf_actv_indc"] = prefix .. "aistī" data.forms["3s_perf_actv_indc"] = prefix .. "ait"

data.forms["2s_pres_actv_subj"] = prefix .. "aiiās" data.forms["3s_pres_actv_subj"] = prefix .. "aiiat" data.forms["3p_pres_actv_subj"] = prefix .. "aiiant"

data.forms["2s_pres_actv_impr"] = prefix .. "ai"

data.forms["pres_actv_inf"] = prefix .. "aiiere" data.forms["pres_actv_ptc"] = prefix .. "aiiēns" end

irreg_conjugations["ajo"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation iō-variant") table.insert(data.title, "irregular") table.insert(data.title, "active only") table.insert(data.title, "highly defective") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin active-only verbs") table.insert(data.categories, "Latin defective verbs")

-- Signal to to display the verb as irregular and highly defective typeinfo.subtypes.irreg = true typeinfo.subtypes.highlydef = true

local prefix = typeinfo.prefix or ""

data.forms["1s_pres_actv_indc"] = prefix .. "ajō" data.forms["2s_pres_actv_indc"] = prefix .. "ais" data.forms["3s_pres_actv_indc"] = prefix .. "ait" data.forms["3p_pres_actv_indc"] = prefix .. "ajunt"

data.forms["1s_impf_actv_indc"] = prefix .. "ajēbam" data.forms["2s_impf_actv_indc"] = prefix .. "ajēbās" data.forms["3s_impf_actv_indc"] = prefix .. "ajēbat" data.forms["1p_impf_actv_indc"] = prefix .. "ajēbāmus" data.forms["2p_impf_actv_indc"] = prefix .. "ajēbātis" data.forms["3p_impf_actv_indc"] = prefix .. "ajēbant"

data.forms["2s_perf_actv_indc"] = prefix .. "aistī" data.forms["3s_perf_actv_indc"] = prefix .. "ait"

data.forms["2s_pres_actv_subj"] = prefix .. "ajās" data.forms["3s_pres_actv_subj"] = prefix .. "ajat" data.forms["3p_pres_actv_subj"] = prefix .. "ajant"

data.forms["2s_pres_actv_impr"] = prefix .. "ai"

data.forms["pres_actv_inf"] = prefix .. "ajere" data.forms["pres_actv_ptc"] = prefix .. "ajēns" end

irreg_conjugations["dico"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation") table.insert(data.title, "irregular short imperative") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs")

local prefix = typeinfo.prefix or ""

make_pres_3rd(data, typeinfo, prefix .. "dīc") make_perf(data, prefix .. "dīx") make_supine(data, typeinfo, prefix .. "dict") make_sigm(data, typeinfo, prefix .. "dīx") --Archaic regular imperative local noteindex = #(data.footnotes) + 1 add_form(data, "2s_pres_actv_impr", prefix, "dīc", 1) data.form_footnote_indices["2s_pres_actv_impr"] = tostring(noteindex) --Archaic future forms if prefix == "" then add_form(data, "1s_futr_actv_indc", "", "dīcēbō", 2 ) add_form(data, "3s_futr_actv_indc", "", "dīcēbit", 2 ) data.form_footnote_indices["1s_futr_actv_indc"] = tostring(noteindex) data.form_footnote_indices["3s_futr_actv_indc"] = tostring(noteindex) end data.footnotes[noteindex] = 'Archaic.' end

irreg_conjugations["do"] = function(args, data, typeinfo) table.insert(data.title, "first conjugation") table.insert(data.title, "irregular short a in most forms except " .. make_link({lang = lang, alt = "dās"}, "term") .. " and " .. make_link({lang = lang, alt = "dā"}, "term")) table.insert(data.categories, "Latin first conjugation verbs") table.insert(data.categories, "Latin irregular verbs")

-- Signal to to display the verb as irregular typeinfo.subtypes.irreg = true

local prefix = typeinfo.prefix or ""

make_perf(data, prefix .. "ded") make_supine(data, typeinfo, prefix .. "dat")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", prefix, "dō", "dās", "dat", "damus", "datis", "dant") add_forms(data, "impf_actv_indc", prefix, "dabam", "dabās", "dabat", "dabāmus", "dabātis", "dabant") add_forms(data, "futr_actv_indc", prefix, "dabō", "dabis", "dabit", "dabimus", "dabitis", "dabunt")

-- Passive imperfective indicative add_forms(data, "pres_pasv_indc", prefix, "dor", {"daris", "dare"}, "datur", "damur", "daminī", "dantur") add_forms(data, "impf_pasv_indc", prefix, "dabar", {"dabāris", "dabāre"}, "dabātur", "dabāmur", "dabāminī", "dabantur") add_forms(data, "futr_pasv_indc", prefix, "dabor", {"daberis", "dabere"}, "dabitur", "dabimur", "dabiminī", "dabuntur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", prefix, "dem", "dēs", "det", "dēmus", "dētis", "dent") add_forms(data, "impf_actv_subj", prefix, "darem", "darēs", "daret", "darēmus", "darētis", "darent")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", prefix, "der", {"dēris", "dēre"}, "dētur", "dēmur", "dēminī", "dentur") add_forms(data, "impf_pasv_subj", prefix, "darer", {"darēris", "darēre"}, "darētur", "darēmur", "darēminī", "darentur")

-- Imperative add_2_forms(data, "pres_actv_impr", prefix, "dā", "date") add_23_forms(data, "futr_actv_impr", prefix, "datō", "datō", "datōte", "dantō")

add_2_forms(data, "pres_pasv_impr", prefix, "dare", "daminī") -- no 2p form add_23_forms(data, "futr_pasv_impr", prefix, "dator", "dator", {}, "dantor")

-- Present infinitives data.forms["pres_actv_inf"] = prefix .. "dare" data.forms["pres_pasv_inf"] = prefix .. "darī"

-- Imperfective participles data.forms["pres_actv_ptc"] = prefix .. "dāns"

-- Gerund make_gerund(data, typeinfo, prefix .. "dand") end

irreg_conjugations["duco"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation") table.insert(data.title, "irregular short imperative") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs")

local prefix = typeinfo.prefix or ""

make_pres_3rd(data, typeinfo, prefix .. "dūc") make_perf(data, prefix .. "dūx") make_supine(data, typeinfo, prefix .. "duct") make_sigm(data, typeinfo, prefix .. "dūx")

add_form(data, "2s_pres_actv_impr", prefix, "dūc", 1) end

irreg_conjugations["edo"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation") table.insert(data.title, "some irregular alternative forms") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs")

-- Signal to to display the verb as irregular typeinfo.subtypes.irreg = true

local prefix = typeinfo.prefix or ""

make_pres_3rd(data, typeinfo, prefix .. "ed") make_perf(data, prefix .. "ēd") make_supine(data, typeinfo, prefix .. "ēs")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", prefix, {}, "ēs", "ēst", {}, "ēstis", {})

-- Passive imperfective indicative add_form(data, "3s_pres_pasv_indc", prefix, "ēstur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", prefix, "edim", "edīs", "edit", "edīmus", "edītis", "edint") add_forms(data, "impf_actv_subj", prefix, "ēssem", "ēssēs", "ēsset", "ēssēmus", "ēssētis", "ēssent")

-- Active imperative add_2_forms(data, "pres_actv_impr", prefix, "ēs", "ēste") add_23_forms(data, "futr_actv_impr", prefix, "ēstō", "ēstō", "ēstōte", {})

-- Present infinitives add_form(data, "pres_actv_inf", prefix, "ēsse") end

irreg_conjugations["eo"] = function(args, data, typeinfo) table.insert(data.title, "irregular") table.insert(data.categories, "Latin irregular verbs")

local prefix = typeinfo.prefix or ""

make_perf(data, prefix .. "i") make_supine(data, typeinfo, prefix .. "it")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", prefix, "eō", "īs", "it", "īmus", "ītis",		prefix == "prōd" and {"eunt", "īnunt"} or "eunt") add_forms(data, "impf_actv_indc", prefix, "ībam", "ībās", "ībat", "ībāmus", "ībātis", "ībant") add_forms(data, "futr_actv_indc", prefix, "ībō", "ībis", "ībit", "ībimus", "ībitis", "ībunt")

-- Active perfective indicative add_form(data, "1s_perf_actv_indc", prefix, "īvī") data.forms["2s_perf_actv_indc"] = {prefix .. "īstī", prefix .. "īvistī"} add_form(data, "3s_perf_actv_indc", prefix, "īvit") data.forms["2p_perf_actv_indc"] = prefix .. "īstis"

-- Passive imperfective indicative add_forms(data, "pres_pasv_indc", prefix, "eor", { "īris", "īre"}, "ītur", "īmur", "īminī", "euntur") add_forms(data, "impf_pasv_indc", prefix, "ībar", {"ībāris", "ībāre"}, "ībātur", "ībāmur", "ībāminī", "ībantur") add_forms(data, "futr_pasv_indc", prefix, "ībor", {"īberis", "ībere"}, "ībitur", "ībimur", "ībiminī", "ībuntur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", prefix, "eam", "eās", "eat", "eāmus", "eātis", "eant") add_forms(data, "impf_actv_subj", prefix, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")

-- Active perfective subjunctive data.forms["1s_plup_actv_subj"] = prefix .. "īssem" data.forms["2s_plup_actv_subj"] = prefix .. "īssēs" data.forms["3s_plup_actv_subj"] = prefix .. "īsset" data.forms["1p_plup_actv_subj"] = prefix .. "īssēmus" data.forms["2p_plup_actv_subj"] = prefix .. "īssētis" data.forms["3p_plup_actv_subj"] = prefix .. "īssent"

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", prefix, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur") add_forms(data, "impf_pasv_subj", prefix, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")

-- Imperative add_2_forms(data, "pres_actv_impr", prefix, "ī", "īte") add_23_forms(data, "futr_actv_impr", prefix, "ītō", "ītō", "ītōte", "euntō")

add_2_forms(data, "pres_pasv_impr", prefix, "īre", "īminī") add_23_forms(data, "futr_pasv_impr", prefix, "ītor", "ītor", {}, "euntor")

-- Present infinitives data.forms["pres_actv_inf"] = prefix .. "īre" data.forms["pres_pasv_inf"] = prefix .. "īrī"

-- Perfect/future infinitives data.forms["perf_actv_inf"] = prefix .. "īsse"

-- Imperfective participles data.forms["pres_actv_ptc"] = prefix .. "iēns"

-- Gerund make_gerund(data, typeinfo, prefix .. "eund") end

local function fio(data, prefix, voice) -- Active/passive imperfective indicative add_forms(data, "pres_" .. voice .. "_indc", prefix,		"fīō", "fīs", "fit", "fīmus", "fītis", "fīunt") add_forms(data, "impf_" .. voice .. "_indc", prefix .. "fīēb",		"am", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "futr_" .. voice .. "_indc", prefix .. "fī",		"am", "ēs", "et", "ēmus", "ētis", "ent")

-- Active/passive imperfective subjunctive add_forms(data, "pres_" .. voice .. "_subj", prefix .. "fī",		"am", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "impf_" .. voice .. "_subj", prefix .. "fier",		"em", "ēs", "et", "ēmus", "ētis", "ent")

-- Active/passive imperative add_2_forms(data, "pres_" .. voice .. "_impr", prefix .. "fī", "", "te") add_23_forms(data, "futr_" .. voice .. "_impr", prefix .. "fī", "tō", "tō", "tōte", "untō")

-- Active/passive present infinitive add_form(data, "pres_" .. voice .. "_inf", prefix, "fierī") end

irreg_conjugations["facio"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation iō-variant") table.insert(data.title, "irregular and partially suppletive in the passive") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

local prefix = typeinfo.prefix or ""

make_pres_3rd_io(data, typeinfo, prefix .. "fac", "nopass") -- We said no passive, but we do want the future passive participle. make_gerund(data, typeinfo, prefix .. "faciend", "und-variant", "no-gerund")

make_perf(data, prefix .. "fēc") make_supine(data, typeinfo, prefix .. "fact") make_sigm(data, typeinfo, prefix .. "fax")

if prefix == "" then -- Active imperative add_form(data, "2s_pres_actv_impr", "", "fac", 1) -- Sigmatic forms add_form(data, "1s_sigf_actv_indc", "", {"faxsō", "facsō", "faxiō"}, 2) add_form(data, "2s_sigf_actv_indc", "", {"faxsis", "facsis", "facxis", "facxsis"}, 2) add_form(data, "3s_sigf_actv_indc", "", "faxsit", 2) add_form(data, "1p_sigf_actv_indc", "", "faxsimus", 2) add_form(data, "2p_sigf_actv_indc", "", "faxsitis", 2) add_form(data, "3p_sigf_actv_indc", "", "faxsint", 2) add_form(data, "1s_siga_actv_subj", "", {"faxsim", "faxēm"}, 2) add_form(data, "2s_siga_actv_subj", "", {"faxsīs", "faxseis", "faxeis", "faxēs"}, 2) add_form(data, "3s_siga_actv_subj", "", {"faxsīt", "faxeit", "faxēt"}, 2) add_form(data, "1p_siga_actv_subj", "", {"faxsīmus", "faxeimus"}, 2) add_form(data, "2p_siga_actv_subj", "", {"faxsītis", "faxeitis"}, 2) add_form(data, "3p_siga_actv_subj", "", {"faxsint", "faxēnt"}, 2) end

fio(data, prefix, "pasv") end

irreg_conjugations["fio"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation iō-variant") table.insert(data.title, "irregular long ī") if not typeinfo.subtypes.nosup then table.insert(data.title, "suppletive in the supine stem") end table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

local prefix = typeinfo.prefix or ""

typeinfo.subtypes.semidepon = true

fio(data, prefix, "actv")

make_supine(data, typeinfo, prefix .. "fact")

-- Perfect/future infinitives data.forms["futr_actv_inf"] = data.forms["futr_pasv_inf"]

-- Imperfective participles data.forms["pres_actv_ptc"] = nil data.forms["futr_actv_ptc"] = nil

-- Gerund make_gerund(data, typeinfo, prefix .. "fiend", "und-variant") end

irreg_conjugations["fero"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation") table.insert(data.title, "irregular") table.insert(data.title, "suppletive") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

-- Signal to to display the verb as irregular typeinfo.subtypes.irreg = true

local prefix_pres = typeinfo.prefix or "" local prefix_perf = ine(args[3]) local prefix_supine = ine(args[4])

prefix_perf = prefix_perf or prefix_pres prefix_supine = prefix_supine or prefix_pres

make_pres_3rd(data, typeinfo, prefix_pres .. "fer") if prefix_perf == "" then make_perf(data, {"tul", "tetul"}) local noteindex = #(data.footnotes) + 1 for slot in iter_slots(false, false) do			if cfind(slot, "perf") or cfind(slot, "plup") or cfind(slot, "futp") then data.form_footnote_indices[slot] = tostring(noteindex) data.footnotes[noteindex] = 'Archaic.' end end else make_perf(data, prefix_perf .. "tul") end make_supine(data, typeinfo, prefix_supine .. "lāt")

-- Active imperfective indicative data.forms["2s_pres_actv_indc"] = prefix_pres .. "fers" data.forms["3s_pres_actv_indc"] = prefix_pres .. "fert" data.forms["2p_pres_actv_indc"] = prefix_pres .. "fertis"

-- Passive imperfective indicative data.forms["3s_pres_pasv_indc"] = prefix_pres .. "fertur"

-- Active imperfective subjunctive data.forms["1s_impf_actv_subj"] = prefix_pres .. "ferrem" data.forms["2s_impf_actv_subj"] = prefix_pres .. "ferrēs" data.forms["3s_impf_actv_subj"] = prefix_pres .. "ferret" data.forms["1p_impf_actv_subj"] = prefix_pres .. "ferrēmus" data.forms["2p_impf_actv_subj"] = prefix_pres .. "ferrētis" data.forms["3p_impf_actv_subj"] = prefix_pres .. "ferrent"

-- Passive present indicative data.forms["2s_pres_pasv_indc"] = {prefix_pres .. "ferris", prefix_pres .. "ferre"}

-- Passive imperfective subjunctive data.forms["1s_impf_pasv_subj"] = prefix_pres .. "ferrer" data.forms["2s_impf_pasv_subj"] = {prefix_pres .. "ferrēris", prefix_pres .. "ferrēre"} data.forms["3s_impf_pasv_subj"] = prefix_pres .. "ferrētur" data.forms["1p_impf_pasv_subj"] = prefix_pres .. "ferrēmur" data.forms["2p_impf_pasv_subj"] = prefix_pres .. "ferrēminī" data.forms["3p_impf_pasv_subj"] = prefix_pres .. "ferrentur"

-- Imperative data.forms["2s_pres_actv_impr"] = prefix_pres .. "fer" data.forms["2p_pres_actv_impr"] = prefix_pres .. "ferte"

data.forms["2s_futr_actv_impr"] = prefix_pres .. "fertō" data.forms["3s_futr_actv_impr"] = prefix_pres .. "fertō" data.forms["2p_futr_actv_impr"] = prefix_pres .. "fertōte"

data.forms["2s_pres_pasv_impr"] = prefix_pres .. "ferre"

data.forms["2s_futr_pasv_impr"] = prefix_pres .. "fertor" data.forms["3s_futr_pasv_impr"] = prefix_pres .. "fertor"

-- Present infinitives data.forms["pres_actv_inf"] = prefix_pres .. "ferre" data.forms["pres_pasv_inf"] = prefix_pres .. "ferrī" end

irreg_conjugations["inquam"] = function(args, data, typeinfo) table.insert(data.title, "irregular") table.insert(data.title, "highly defective") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin defective verbs")

-- Signal to to display the verb as highly defective -- (it already displays as irregular because conj == "irreg" and	-- subconj == "irreg") typeinfo.subtypes.highlydef = true

data.forms["1s_pres_actv_indc"] = "inquam" data.forms["2s_pres_actv_indc"] = "inquis" data.forms["3s_pres_actv_indc"] = "inquit" data.forms["1p_pres_actv_indc"] = "inquimus" data.forms["2p_pres_actv_indc"] = "inquitis" data.forms["3p_pres_actv_indc"] = "inquiunt"

data.forms["2s_futr_actv_indc"] = "inquiēs" data.forms["3s_futr_actv_indc"] = "inquiet"

data.forms["3s_impf_actv_indc"] = "inquiēbat"

data.forms["1s_perf_actv_indc"] = "inquiī" data.forms["2s_perf_actv_indc"] = "inquistī" data.forms["3s_perf_actv_indc"] = "inquit"

data.forms["3s_pres_actv_subj"] = "inquiat"

data.forms["2s_pres_actv_impr"] = "inque" data.forms["2s_futr_actv_impr"] = "inquitō" data.forms["3s_futr_actv_impr"] = "inquitō"

data.forms["pres_actv_ptc"] = "inquiēns" end

local function libet_lubet(data, typeinfo, stem) table.insert(data.title, "second conjugation") table.insert(data.title, "mostly impersonal") table.insert(data.categories, "Latin second conjugation verbs") table.insert(data.categories, "Latin impersonal verbs")

typeinfo.subtypes.nopass = true local prefix = typeinfo.prefix or ""

stem = prefix .. stem

-- Active imperfective indicative data.forms["3s_pres_actv_indc"] = stem .. "et"

data.forms["3s_impf_actv_indc"] = stem .. "ēbat"

data.forms["3s_futr_actv_indc"] = stem .. "ēbit"

-- Active perfective indicative data.forms["3s_perf_actv_indc"] = {stem .. "uit", "" .. stem .. "itum est"}

data.forms["3s_plup_actv_indc"] = {stem .. "uerat", "" .. stem .. "itum erat"}

data.forms["3s_futp_actv_indc"] = {stem .. "uerit", "" .. stem .. "itum erit"}

-- Active imperfective subjunctive data.forms["3s_pres_actv_subj"] = stem .. "eat"

data.forms["3s_impf_actv_subj"] = stem .. "ēret"

-- Active perfective subjunctive data.forms["3s_perf_actv_subj"] = {stem .. "uerit", "" .. stem .. "itum sit"}

data.forms["3s_plup_actv_subj"] = {stem .. "uisset", "" .. stem .. "itum esset"} data.forms["3p_plup_actv_subj"] = stem .. "uissent"

-- Present infinitives data.forms["pres_actv_inf"] = stem .. "ēre"

-- Perfect infinitive data.forms["perf_actv_inf"] = {stem .. "uisse", "" .. stem .. "itum esse"}

-- Imperfective participles data.forms["pres_actv_ptc"] = stem .. "ēns" data.forms["perf_actv_ptc"] = stem .. "itum" end

irreg_conjugations["libet"] = function(args, data, typeinfo) libet_lubet(data, typeinfo, "lib") end

irreg_conjugations["lubet"] = function(args, data, typeinfo) libet_lubet(data, typeinfo, "lub") end

irreg_conjugations["licet"] = function(args, data, typeinfo) table.insert(data.title, "second conjugation") table.insert(data.title, "mostly impersonal") table.insert(data.categories, "Latin second conjugation verbs") table.insert(data.categories, "Latin impersonal verbs")

typeinfo.subtypes.nopass = true

-- Active imperfective indicative data.forms["3s_pres_actv_indc"] = "licet" data.forms["3p_pres_actv_indc"] = "licent"

data.forms["3s_impf_actv_indc"] = "licēbat" data.forms["3p_impf_actv_indc"] = "licēbant"

data.forms["3s_futr_actv_indc"] = "licēbit"

-- Active perfective indicative data.forms["3s_perf_actv_indc"] = {"licuit", "licitum est"}

data.forms["3s_plup_actv_indc"] = {"licuerat", "licitum erat"}

data.forms["3s_futp_actv_indc"] = {"licuerit", "licitum erit"}

-- Active imperfective subjunctive data.forms["3s_pres_actv_subj"] = "liceat" data.forms["3p_pres_actv_subj"] = "liceant"

data.forms["3s_impf_actv_subj"] = "licēret"

-- Perfective subjunctive data.forms["3s_perf_actv_subj"] = {"licuerit", "licitum sit"}

data.forms["3s_plup_actv_subj"] = {"licuisset", "licitum esset"}

-- Imperative data.forms["2s_futr_actv_impr"] = "licētō" data.forms["3s_futr_actv_impr"] = "licētō"

-- Infinitives data.forms["pres_actv_inf"] = "licēre" data.forms["perf_actv_inf"] = {"licuisse", "licitum esse"} data.forms["futr_actv_inf"] = "licitūrum esse"

-- Participles data.forms["pres_actv_ptc"] = "licēns" data.forms["perf_actv_ptc"] = "licitus" data.forms["futr_actv_ptc"] = "licitūrus" end

-- Handle most forms of volō, mālō, nōlō. local function volo_malo_nolo(data, indc_stem, subj_stem) -- Present active indicative needs to be done individually as each -- verb is different. add_forms(data, "impf_actv_indc", indc_stem .. "ēb", "am", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "futr_actv_indc", indc_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", subj_stem, "im", "īs", "it", "īmus", "ītis", "int") add_forms(data, "impf_actv_subj", subj_stem .. "l", "em", "ēs", "et", "ēmus", "ētis", "ent")

-- Present infinitives data.forms["pres_actv_inf"] = subj_stem .. "le"

-- Imperfective participles data.forms["pres_actv_ptc"] = indc_stem .. "ēns" end

irreg_conjugations["volo"] = function(args, data, typeinfo) table.insert(data.title, "irregular") table.insert(data.title, "suppletive in the second-person singular indicative present") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

local prefix = typeinfo.prefix or ""

typeinfo.subtypes.nopass = true typeinfo.subtypes.noimp = true make_perf(data, prefix .. "volu")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", prefix,		"volō", "vīs", prefix ~= "" and "vult" or {"vult", "volt"},		"volumus", prefix ~= "" and "vultis" or {"vultis", "voltis"}, "volunt") volo_malo_nolo(data, prefix .. "vol", prefix .. "vel") end

irreg_conjugations["malo"] = function(args, data, typeinfo) table.insert(data.title, "irregular") table.insert(data.title, "suppletive in the second-person singular indicative present") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

typeinfo.subtypes.nopass = true typeinfo.subtypes.noimp = true make_perf(data, "mālu")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", "",		"mālō", "māvīs", "māvult", "mālumus", "māvultis", "mālunt") volo_malo_nolo(data, "māl", "māl") end

irreg_conjugations["nolo"] = function(args, data, typeinfo) table.insert(data.title, "irregular") table.insert(data.title, "suppletive in the second-person singular indicative present") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

typeinfo.subtypes.nopass = true make_perf(data, "nōlu")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", "",		"nōlō", "nōn vīs", "nōn vult", "nōlumus", "nōn vultis", "nōlunt") add_forms(data, "impf_actv_indc", "nōlēb", "am", "ās", "at", "āmus", "ātis", "ant") volo_malo_nolo(data, "nōl", "nōl")

-- Imperative add_2_forms(data, "pres_actv_impr", "nōlī", "", "te") add_23_forms(data, "futr_actv_impr", "nōl", "itō", "itō", "itōte", "untō") end

irreg_conjugations["possum"] = function(args, data, typeinfo) table.insert(data.title, "highly irregular") table.insert(data.title, "suppletive") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

typeinfo.subtypes.nopass = true make_perf(data, "potu")

-- Active imperfective indicative add_forms(data, "pres_actv_indc", "", "possum", "potes", "potest",		"possumus", "potestis", "possunt") add_forms(data, "impf_actv_indc", "poter", "am", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "futr_actv_indc", "poter", "ō", {"is", "e"}, "it", "imus", "itis", "unt")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", "poss", "im", "īs", "it", "īmus", "ītis", "int") add_forms(data, "impf_actv_subj", "poss", "em", "ēs", "et", "ēmus", "ētis", "ent")

-- Present infinitives data.forms["pres_actv_inf"] = "posse"

-- Imperfective participles data.forms["pres_actv_ptc"] = "potēns" end

irreg_conjugations["piget"] = function(args, data, typeinfo) table.insert(data.title, "second conjugation") table.insert(data.title, "impersonal") table.insert(data.title, "semi-deponent") table.insert(data.categories, "Latin second conjugation verbs") table.insert(data.categories, "Latin impersonal verbs") table.insert(data.categories, "Latin semi-deponent verbs") table.insert(data.categories, "Latin defective verbs")

local prefix = typeinfo.prefix or ""

--	-- not used	local ppplink = make_link({lang = lang, term = prefix .. "ausus"}, "term")	local sumlink = make_link({lang = lang, term = "sum"}, "term")	--

data.forms["3s_pres_actv_indc"] = prefix .. "piget"

data.forms["3s_impf_actv_indc"] = prefix .. "pigēbat"

data.forms["3s_futr_actv_indc"] = prefix .. "pigēbit"

data.forms["3s_perf_actv_indc"] = {prefix .. "piguit", "" .. prefix .. "pigitum est"}

data.forms["3s_plup_actv_indc"] = {prefix .. "piguerat", "" .. prefix .. "pigitum erat"}

data.forms["3s_futp_actv_indc"] = {prefix .. "piguerit", "" .. prefix .. "pigitum erit"}

data.forms["3s_pres_actv_subj"] = prefix .. "pigeat"

data.forms["3s_impf_actv_subj"] = prefix .. "pigēret"

data.forms["3s_perf_actv_subj"] = {prefix .. "piguerit", "" .. prefix .. "pigitum sit"}

data.forms["3s_plup_actv_subj"] = {prefix .. "piguisset", "" .. prefix .. "pigitum esset"}

data.forms["pres_actv_inf"] = prefix .. "pigēre" data.forms["perf_actv_inf"] = "" .. prefix .. "pigitum esse" data.forms["pres_actv_ptc"] = prefix .. "pigēns" data.forms["perf_actv_ptc"] = prefix .. "pigitum"

-- Gerund make_gerund(data, typeinfo, prefix .. "pigend") end

irreg_conjugations["coepi"] = function(args, data, typeinfo) table.insert(data.title, "third conjugation") table.insert(data.title, "no present stem") table.insert(data.categories, "Latin third conjugation verbs") table.insert(data.categories, "Latin verbs with missing present stem") table.insert(data.categories, "Latin defective verbs")

local prefix = typeinfo.prefix or ""

make_perf(data, prefix .. "coep") make_supine(data, typeinfo, prefix .. "coept") make_perfect_passive(data) end

-- The vowel of the prefix is lengthened if it ends in -n and the next word begins with f- or s-. local function lengthen_prefix(prefix) return prefix:gsub("([aeiou]n)$", {["an"] = "ān", ["en"] = "ēn", ["in"] = "īn", ["on"] = "ōn", ["un"] = "ūn"}) end

irreg_conjugations["sum"] = function(args, data, typeinfo) table.insert(data.title, "highly irregular") table.insert(data.title, "suppletive") table.insert(data.categories, "Latin irregular verbs") table.insert(data.categories, "Latin suppletive verbs")

local prefix = typeinfo.prefix or "" local prefix_e = ine(args[3]) or prefix local prefix_f = lengthen_prefix(ine(args[4]) or prefix) local prefix_s = lengthen_prefix(prefix)

typeinfo.subtypes.nopass = true typeinfo.subtypes.supfutractvonly = true make_perf(data, prefix_f .. "fu") make_supine(data, typeinfo, prefix_f .. "fut")

-- Active imperfective indicative data.forms["1s_pres_actv_indc"] = prefix_s .. "sum" data.forms["2s_pres_actv_indc"] = prefix_e .. "es" data.forms["3s_pres_actv_indc"] = prefix_e .. "est" data.forms["1p_pres_actv_indc"] = prefix_s .. "sumus" data.forms["2p_pres_actv_indc"] = prefix_e .. "estis" data.forms["3p_pres_actv_indc"] = prefix_s .. "sunt"

data.forms["1s_impf_actv_indc"] = prefix_e .. "eram" data.forms["2s_impf_actv_indc"] = prefix_e .. "erās" data.forms["3s_impf_actv_indc"] = prefix_e .. "erat" data.forms["1p_impf_actv_indc"] = prefix_e .. "erāmus" data.forms["2p_impf_actv_indc"] = prefix_e .. "erātis" data.forms["3p_impf_actv_indc"] = prefix_e .. "erant"

data.forms["1s_futr_actv_indc"] = prefix_e .. "erō" data.forms["2s_futr_actv_indc"] = {prefix_e .. "eris", prefix_e .. "ere"} data.forms["3s_futr_actv_indc"] = prefix_e .. "erit" data.forms["1p_futr_actv_indc"] = prefix_e .. "erimus" data.forms["2p_futr_actv_indc"] = prefix_e .. "eritis" data.forms["3p_futr_actv_indc"] = prefix_e .. "erunt"

-- Active imperfective subjunctive data.forms["1s_pres_actv_subj"] = prefix_s .. "sim" data.forms["2s_pres_actv_subj"] = prefix_s .. "sīs" data.forms["3s_pres_actv_subj"] = prefix_s .. "sit" data.forms["1p_pres_actv_subj"] = prefix_s .. "sīmus" data.forms["2p_pres_actv_subj"] = prefix_s .. "sītis" data.forms["3p_pres_actv_subj"] = prefix_s .. "sint" if prefix_s == "ad" then local noteindex = #(data.footnotes) + 1 add_form(data, "3p_pres_actv_subj", "", "adessint", 2 ) data.form_footnote_indices["3p_pres_actv_subj"] = tostring(noteindex) data.footnotes[noteindex] = 'Archaic.' end

data.forms["1s_impf_actv_subj"] = {prefix_e .. "essem", prefix_f .. "forem"} data.forms["2s_impf_actv_subj"] = {prefix_e .. "essēs", prefix_f .. "forēs"} data.forms["3s_impf_actv_subj"] = {prefix_e .. "esset", prefix_f .. "foret"} data.forms["1p_impf_actv_subj"] = {prefix_e .. "essēmus", prefix_f .. "forēmus"} data.forms["2p_impf_actv_subj"] = {prefix_e .. "essētis", prefix_f .. "forētis"} data.forms["3p_impf_actv_subj"] = {prefix_e .. "essent", prefix_f .. "forent"}

-- Imperative data.forms["2s_pres_actv_impr"] = prefix_e .. "es" data.forms["2p_pres_actv_impr"] = prefix_e .. "este"

data.forms["2s_futr_actv_impr"] = prefix_e .. "estō" data.forms["3s_futr_actv_impr"] = prefix_e .. "estō" data.forms["2p_futr_actv_impr"] = prefix_e .. "estōte" data.forms["3p_futr_actv_impr"] = prefix_s .. "suntō"

-- Present infinitives data.forms["pres_actv_inf"] = prefix_e .. "esse"

-- Future infinitives data.forms["futr_actv_inf"] = {"" .. prefix_f .. "futūrum esse", prefix_f .. "fore"}

-- Imperfective participles if prefix == "ab" then data.forms["pres_actv_ptc"] = "absēns" elseif prefix == "prae" then data.forms["pres_actv_ptc"] = "praesēns" end

-- Gerund data.forms["ger_gen"] = nil data.forms["ger_dat"] = nil data.forms["ger_acc"] = nil data.forms["ger_abl"] = nil

-- Supine data.forms["sup_acc"] = nil data.forms["sup_abl"] = nil end

-- Form-generating functions

make_pres_1st = function(data, typeinfo, pres_stem) if not pres_stem then return end

-- Active imperfective indicative add_forms(data, "pres_actv_indc", pres_stem, "ō", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "impf_actv_indc", pres_stem, "ābam", "ābās", "ābat", "ābāmus", "ābātis", "ābant") add_forms(data, "futr_actv_indc", pres_stem, "ābō", "ābis", "ābit", "ābimus", "ābitis", "ābunt")

-- Passive imperfective indicative add_forms(data, "pres_pasv_indc", pres_stem, "or", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur") add_forms(data, "impf_pasv_indc", pres_stem, "ābar", {"ābāris", "ābāre"}, "ābātur", "ābāmur", "ābāminī", "ābantur") add_forms(data, "futr_pasv_indc", pres_stem, "ābor", {"āberis", "ābere"}, "ābitur", "ābimur", "ābiminī", "ābuntur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", pres_stem, "em", "ēs", "et", "ēmus", "ētis", "ent") add_forms(data, "impf_actv_subj", pres_stem, "ārem", "ārēs", "āret", "ārēmus", "ārētis", "ārent")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", pres_stem, "er", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur") add_forms(data, "impf_pasv_subj", pres_stem, "ārer", {"ārēris", "ārēre"}, "ārētur", "ārēmur", "ārēminī", "ārentur")

-- Imperative add_2_forms(data, "pres_actv_impr", pres_stem, "ā", "āte") add_23_forms(data, "futr_actv_impr", pres_stem, "ātō", "ātō", "ātōte", "antō")

add_2_forms(data, "pres_pasv_impr", pres_stem, "āre", "āminī") add_23_forms(data, "futr_pasv_impr", pres_stem, "ātor", "ātor", {}, "antor")

-- Present infinitives data.forms["pres_actv_inf"] = pres_stem .. "āre" data.forms["pres_pasv_inf"] = pres_stem .. "ārī"

-- Imperfective participles data.forms["pres_actv_ptc"] = pres_stem .. "āns"

-- Gerund make_gerund(data, typeinfo, pres_stem .. "and") end

make_pres_2nd = function(data, typeinfo, pres_stem, nopass, noimpr) -- Active imperfective indicative add_forms(data, "pres_actv_indc", pres_stem, "eō", "ēs", "et", "ēmus", "ētis", "ent") add_forms(data, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant") add_forms(data, "futr_actv_indc", pres_stem, "ēbō", "ēbis", "ēbit", "ēbimus", "ēbitis", "ēbunt")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", pres_stem, "eam", "eās", "eat", "eāmus", "eātis", "eant") add_forms(data, "impf_actv_subj", pres_stem, "ērem", "ērēs", "ēret", "ērēmus", "ērētis", "ērent")

-- Active imperative if not noimpr then add_2_forms(data, "pres_actv_impr", pres_stem, "ē", "ēte") add_23_forms(data, "futr_actv_impr", pres_stem, "ētō", "ētō", "ētōte", "entō") end

if not nopass then -- Passive imperfective indicative add_forms(data, "pres_pasv_indc", pres_stem, "eor", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur") add_forms(data, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur") add_forms(data, "futr_pasv_indc", pres_stem, "ēbor", {"ēberis", "ēbere"}, "ēbitur", "ēbimur", "ēbiminī", "ēbuntur")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", pres_stem, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur") add_forms(data, "impf_pasv_subj", pres_stem, "ērer", {"ērēris", "ērēre"}, "ērētur", "ērēmur", "ērēminī", "ērentur")

-- Passive imperative if not noimpr then add_2_forms(data, "pres_pasv_impr", pres_stem, "ēre", "ēminī") add_23_forms(data, "futr_pasv_impr", pres_stem, "ētor", "ētor", {}, "entor") end end

-- Present infinitives data.forms["pres_actv_inf"] = pres_stem .. "ēre" if not nopass then data.forms["pres_pasv_inf"] = pres_stem .. "ērī" end

-- Imperfective participles data.forms["pres_actv_ptc"] = pres_stem .. "ēns"

-- Gerund make_gerund(data, typeinfo, pres_stem .. "end", nil, nil, nopass) end

make_pres_3rd = function(data, typeinfo, pres_stem) -- Active imperfective indicative add_forms(data, "pres_actv_indc", pres_stem, "ō", "is", "it", "imus", "itis", "unt") add_forms(data, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant") add_forms(data, "futr_actv_indc", pres_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")

-- Passive imperfective indicative add_forms(data, "pres_pasv_indc", pres_stem, "or", {"eris", "ere"}, "itur", "imur", "iminī", "untur") add_forms(data, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur") add_forms(data, "futr_pasv_indc", pres_stem, "ar", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", pres_stem, "am", "ās", "at", "āmus", "ātis", "ant") add_forms(data, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", pres_stem, "ar", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur") add_forms(data, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")

-- Imperative add_2_forms(data, "pres_actv_impr", pres_stem, "e", "ite") add_23_forms(data, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "untō")

add_2_forms(data, "pres_pasv_impr", pres_stem, "ere", "iminī") add_23_forms(data, "futr_pasv_impr", pres_stem, "itor", "itor", {}, "untor")

-- Present infinitives data.forms["pres_actv_inf"] = pres_stem .. "ere" data.forms["pres_pasv_inf"] = pres_stem .. "ī"

-- Imperfective participles data.forms["pres_actv_ptc"] = pres_stem .. "ēns"

-- Gerund make_gerund(data, typeinfo, pres_stem .. "end", "und-variant") end

make_pres_3rd_io = function(data, typeinfo, pres_stem, nopass) -- Active imperfective indicative add_forms(data, "pres_actv_indc", pres_stem, "iō", "is", "it", "imus", "itis", "iunt") add_forms(data, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant") add_forms(data, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant") add_forms(data, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")

-- Active imperative add_2_forms(data, "pres_actv_impr", pres_stem, "e", "ite") add_23_forms(data, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "iuntō")

-- Passive imperfective indicative if not nopass then add_forms(data, "pres_pasv_indc", pres_stem, "ior", {"eris", "ere"}, "itur", "imur", "iminī", "iuntur") add_forms(data, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur") add_forms(data, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur") add_forms(data, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")

-- Passive imperative add_2_forms(data, "pres_pasv_impr", pres_stem, "ere", "iminī") add_23_forms(data, "futr_pasv_impr", pres_stem, "itor", "itor", {}, "iuntor") end

-- Present infinitives data.forms["pres_actv_inf"] = pres_stem .. "ere" if not nopass then data.forms["pres_pasv_inf"] = pres_stem .. "ī" end

-- Imperfective participles data.forms["pres_actv_ptc"] = pres_stem .. "iēns"

-- Gerund make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant", nil, nopass) end

make_pres_4th = function(data, typeinfo, pres_stem) -- Active imperfective indicative add_forms(data, "pres_actv_indc", pres_stem, "iō", "īs", "it", "īmus", "ītis", "iunt") add_forms(data, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant") add_forms(data, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")

-- Passive imperfective indicative add_forms(data, "pres_pasv_indc", pres_stem, "ior", {"īris", "īre"}, "ītur", "īmur", "īminī", "iuntur") add_forms(data, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur") add_forms(data, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")

-- Active imperfective subjunctive add_forms(data, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant") add_forms(data, "impf_actv_subj", pres_stem, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")

-- Passive imperfective subjunctive add_forms(data, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur") add_forms(data, "impf_pasv_subj", pres_stem, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")

-- Imperative add_2_forms(data, "pres_actv_impr", pres_stem, "ī", "īte") add_23_forms(data, "futr_actv_impr", pres_stem, "ītō", "ītō", "ītōte", "iuntō")

add_2_forms(data, "pres_pasv_impr", pres_stem, "īre", "īminī") add_23_forms(data, "futr_pasv_impr", pres_stem, "ītor", "ītor", {}, "iuntor")

-- Present infinitives data.forms["pres_actv_inf"] = pres_stem .. "īre" data.forms["pres_pasv_inf"] = pres_stem .. "īrī"

-- Imperfective participles data.forms["pres_actv_ptc"] = pres_stem .. "iēns"

-- Gerund make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant") end

make_perf_and_supine = function(data, typeinfo) if typeinfo.subtypes.optsemidepon then make_perf(data, typeinfo.perf_stem, "noinf") make_deponent_perf(data, typeinfo.supine_stem) else make_perf(data, typeinfo.perf_stem) make_supine(data, typeinfo, typeinfo.supine_stem) end end

make_perf = function(data, perf_stem, no_inf) if not perf_stem then return end if type(perf_stem) ~= "table" then perf_stem = {perf_stem} end

for _, stem in ipairs(perf_stem) do		-- Perfective indicative add_forms(data, "perf_actv_indc", stem, "ī", "istī", "it", "imus", "istis", {"ērunt", "ēre"}) add_forms(data, "plup_actv_indc", stem, "eram", "erās", "erat", "erāmus", "erātis", "erant") add_forms(data, "futp_actv_indc", stem, "erō", "eris", "erit", "erimus", "eritis", "erint") -- Perfective subjunctive add_forms(data, "perf_actv_subj", stem, "erim", "erīs", "erit", "erīmus", "erītis", "erint") add_forms(data, "plup_actv_subj", stem, "issem", "issēs", "isset", "issēmus", "issētis", "issent")

-- Perfect infinitive if not no_inf then add_form(data, "perf_actv_inf", stem, "isse") end end end

make_deponent_perf = function(data, supine_stem) if not supine_stem then return end if type(supine_stem) ~= "table" then supine_stem = {supine_stem} end

-- Perfect/future infinitives for _, stem in ipairs(supine_stem) do local stems = "" .. stem .. "us " local stemp = "" .. stem .. "ī "

add_forms(data, "perf_actv_indc", stems, "sum", "es", "est", {}, {}, {}) add_forms(data, "perf_actv_indc", stemp, {}, {}, {}, "sumus", "estis", "sunt")

add_forms(data, "plup_actv_indc", stems, "eram", "erās", "erat", {}, {}, {}) add_forms(data, "plup_actv_indc", stemp, {}, {}, {}, "erāmus", "erātis", "erant")

add_forms(data, "futp_actv_indc", stems, "erō", "eris", "erit", {}, {}, {}) add_forms(data, "futp_actv_indc", stemp, {}, {}, {}, "erimus", "eritis", "erint")

add_forms(data, "perf_actv_subj", stems, "sim", "sīs", "sit", {}, {}, {}) add_forms(data, "perf_actv_subj", stemp, {}, {}, {}, "sīmus", "sītis", "sint")

add_forms(data, "plup_actv_subj", stems, "essem", "essēs", "esset", {}, {}, {}) add_forms(data, "plup_actv_subj", stemp, {}, {}, {}, "essēmus", "essētis", "essent")

add_form(data, "perf_actv_inf", "", "" .. stem .. "um esse") add_form(data, "futr_actv_inf", "", "" .. stem .. "ūrum esse") add_form(data, "perf_actv_ptc", stem, "us") add_form(data, "futr_actv_ptc", stem, "ūrus")

-- Supine add_form(data, "sup_acc", stem, "um") add_form(data, "sup_abl", stem, "ū") end end

make_supine = function(data, typeinfo, supine_stem) if not supine_stem then return end if type(supine_stem) ~= "table" then supine_stem = {supine_stem} end

-- Perfect/future infinitives for _, stem in ipairs(supine_stem) do		local futr_actv_inf, perf_pasv_inf, futr_pasv_inf, futr_actv_ptc local perf_pasv_ptc_lemma, perf_actv_ptc, perf_actv_ptc_acc -- Perfect/future participles futr_actv_ptc = stem .. "ūrus" if typeinfo.subtypes.passimpers then perf_pasv_ptc_lemma = stem .. "um" perf_pasv_ptc = perf_pasv_ptc_lemma perf_pasv_ptc_acc = perf_pasv_ptc_lemma else perf_pasv_ptc_lemma = stem .. "us" if typeinfo.subtypes.mp then perf_pasv_ptc = stem .. "ī" perf_pasv_ptc_acc = stem .. "ōs" elseif typeinfo.subtypes.fp then perf_pasv_ptc = stem .. "ae" perf_pasv_ptc_acc = stem .. "ās" elseif typeinfo.subtypes.np then perf_pasv_ptc = stem .. "a" perf_pasv_ptc_acc = perf_pasv_ptc elseif typeinfo.subtypes.f then perf_pasv_ptc = stem .. "a" perf_pasv_ptc_acc = stem .. "am" elseif typeinfo.subtypes.n then perf_pasv_ptc = stem .. "um" perf_pasv_ptc_acc = perf_pasv_ptc else perf_pasv_ptc = perf_pasv_ptc_lemma perf_pasv_ptc_acc = stem .. "um" end end

perf_pasv_inf = make_raw_link(perf_pasv_ptc_lemma,			perf_pasv_ptc_acc ~= perf_pasv_ptc_lemma and perf_pasv_ptc_acc or nil) .. " esse" futr_pasv_inf = make_raw_link(stem .. "um") .. " īrī"

-- Exceptions local mortu = { ["conmortu"] = true, ["commortu"] = true, ["dēmortu"] = true, ["ēmortu"] = true, ["inmortu"] = true, ["immortu"] = true, ["inēmortu"] = true, ["intermortu"] = true, ["permortu"] = true, ["praemortu"] = true, ["superēmortu"] = true }		local ort = { ["ort"] = true, ["abort"] = true, ["adort"] = true, ["coort"] = true, ["exort"] = true, ["hort"] = true, ["obort"] = true }		if mortu[stem] then futr_actv_ptc = stem:gsub("mortu$", "moritūrus") elseif ort[stem] then futr_actv_ptc = stem:gsub("ort$", "oritūrus") elseif stem == "mortu" then -- FIXME, are we sure about this? futr_actv_inf = {} futr_actv_ptc = "moritūrus" end

if not futr_actv_inf then futr_actv_inf = make_raw_link(futr_actv_ptc, futr_actv_ptc:gsub("us$", "um")) .. " esse" end

add_form(data, "futr_actv_inf", "", futr_actv_inf) add_form(data, "perf_pasv_inf", "", perf_pasv_inf) add_form(data, "futr_pasv_inf", "", futr_pasv_inf) add_form(data, "futr_actv_ptc", "", futr_actv_ptc) add_form(data, "perf_pasv_ptc", "", perf_pasv_ptc)

-- Supine itself add_form(data, "sup_acc", stem, "um") add_form(data, "sup_abl", stem, "ū") end end

make_sigm = function(data, typeinfo, sigm_stem) if not (typeinfo.subtypes.sigm or typeinfo.subtypes.sigmpasv) then return end if type(sigm_stem) ~= "table" then sigm_stem = {sigm_stem} end local noteindex = #(data.footnotes) + 1 for _, stem in ipairs(sigm_stem) do		-- Deponent verbs use the passive form if typeinfo.subtypes.depon then add_form(data, "1s_sigf_actv_indc", stem, "or") add_form(data, "2s_sigf_actv_indc", stem, "eris") add_form(data, "3s_sigf_actv_indc", stem, "itur") else for _, stem in ipairs(sigm_stem) do				-- Sigmatic future active indicative add_forms(data, "sigf_actv_indc", stem, "ō", "is", "it", "imus", "itis", "int") -- Sigmatic future passive indicative (option) if typeinfo.subtypes.sigmpasv then add_form(data, "1s_sigf_pasv_indc", stem, "or") add_form(data, "2s_sigf_pasv_indc", stem, "eris") add_form(data, "3s_sigf_pasv_indc", stem, "itur") end -- Sigmatic future active subjunctive add_forms(data, "siga_actv_subj", stem, "im", "īs", "īt", "īmus", "ītis", "int") -- Perfect infinitive if not no_inf then add_form(data, "sigm_actv_inf", stem, "ere") end end end end data.form_footnote_indices["sigm"] = noteindex if (typeinfo.subtypes.sigm or typeinfo.subtypes.sigmpasv) and not (typeinfo.subtypes.depon) then data.footnotes[noteindex] = 'At least one use of the archaic \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by Old Latin writers; most notably Plautus and Terence. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\").' if typeinfo.subtypes.sigmpasv then data.footnotes[noteindex] = data.footnotes[noteindex] .. ' It is also attested as having a rare sigmatic future passive indicative form (\"will have been\").' end elseif typeinfo.subtypes.depon then data.footnotes[noteindex] = 'At least one use of the archaic \"sigmatic future\" tense is attested, which is used by Old Latin writers; most notably Plautus and Terence. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense.' end end

-- Functions for generating the inflection table

-- Convert FORM (one or more forms) to a string of links. If the form is empty -- (see form_is_empty), the return value will be "&mdash;". local function show_form(form, accel) if not form then return "&mdash;" end

if type(form) ~= "table" then form = {form} end

for key, subform in ipairs(form) do		if form_is_empty(subform) then form[key] = "&mdash;" elseif reconstructed and not subform:find(NAMESPACE .. ":Latin/") then form[key] = make_link({lang = lang, term = NAMESPACE .. ":Latin/" .. subform, alt = subform}) elseif subform:find("[%[%]]") then -- Don't put accelerators on forms already containing links such as			-- the perfect passive infinitive and future active infinitive, or			-- the participles wrongly get tagged as infinitives as well as -- participles. form[key] = make_link({lang = lang, term = subform}) else form[key] = make_link({lang = lang, term = subform, accel = accel}) end end

return table.concat(form, ", ") end

parts_to_tags = { ['1s'] = {'1', 's'}, ['2s'] = {'2', 's'}, ['3s'] = {'3', 's'}, ['1p'] = {'1', 'p'}, ['2p'] = {'2', 'p'}, ['3p'] = {'3', 'p'}, ['actv'] = {'act'}, ['pasv'] = {'pass'}, ['pres'] = {'pres'}, ['impf'] = {'impf'}, ['futr'] = {'fut'}, ['perf'] = {'perf'}, ['plup'] = {'plup'}, ['futp'] = {'fut', 'perf'}, ['sigm'] = {'sigm'}, ['sigf'] = {'sigm', 'fut'}, ['siga'] = {'sigm', 'aor'}, ['indc'] = {'ind'}, ['subj'] = {'sub'}, ['impr'] = {'imp'}, ['inf'] = {'inf'}, ['ptc'] = {'part'}, ['ger'] = {'ger'}, ['sup'] = {'sup'}, ['nom'] = {'nom'}, ['gen'] = {'gen'}, ['dat'] = {'dat'}, ['acc'] = {'acc'}, ['abl'] = {'abl'}, }

-- Call show_form the forms in each non-generic slot (where a -- generic slot is something like pres_actv_indc that covers a whole -- row of slots), converting the forms to a string consisting of -- comma-separated links with accelerators in them. local function convert_forms_into_links(data) local accel_lemma = data.actual_lemma[1] for slot in iter_slots(false, false) do		local slot_parts = split(slot, "_") local tags = {} for _, part in ipairs(slot_parts) do			for _, tag in ipairs(parts_to_tags[part]) do				table.insert(tags, tag) end end

-- put the case first for verbal nouns local accel_slot if tags[1] == "sup" or tags[1] == "ger" then accel_slot = tags[2] .. "|" .. tags[1] else accel_slot = table.concat(tags, "|") end

local accel = {form = accel_slot, lemma = accel_lemma} data.forms[slot] = show_form(data.forms[slot], accel) end end

function export.get_valid_forms(raw_forms) local valid_forms = {} if raw_forms then if type(raw_forms) ~= "table" then raw_forms = {raw_forms} end for _, subform in ipairs(raw_forms) do			if not form_is_empty(subform) then table.insert(valid_forms, subform) end end end return valid_forms end

function export.get_lemma_forms(data, do_linked) local linked_prefix = do_linked and "linked_" or "" for _, slot in ipairs(potential_lemma_slots) do local lemma_forms = export.get_valid_forms(data.forms[linked_prefix .. slot]) if #lemma_forms > 0 then return lemma_forms end end

return nil end

local function get_displayable_lemma(lemma_forms) if not lemma_forms then return "&mdash;" end local lemma_links = {} for _, subform in ipairs(lemma_forms) do		table.insert(lemma_links, make_link({lang = lang, alt = subform}, "term")) end return table.concat(lemma_links, ", ") end

-- Make the table make_table = function(data) local pagename = PAGENAME if reconstructed then pagename = pagename:gsub("Latin/","") end data.actual_lemma = export.get_lemma_forms(data) convert_forms_into_links(data)

return [=[

end

local tenses = { ["pres"] = "present", ["impf"] = "imperfect", ["futr"] = "future", ["perf"] = "perfect", ["plup"] = "pluperfect", ["futp"] = "future perfect", ["sigf"] = "sigmatic future", ["siga"] = "sigmatic aorist" }

local voices = { ["actv"] = "active", ["pasv"] = "passive", }

-- local moods = {	["indc"] = "indicative",	["subj"] = "subjunctive",	["impr"] = "imperative", } --

local nonfins = { ["inf"] = "infinitives", ["ptc"] = "participles", }

-- local verbalnouns = {	["ger"] = "gerund",	["sup"] = "supine", } --

-- local cases = {	["nom"] = "nominative",	["gen"] = "genitive",	["dat"] = "dative",	["acc"] = "accusative",	["abl"] = "ablative", } --

make_indc_rows = function(data) local indc = {}

for _, v in ipairs({"actv", "pasv"}) do		local group = {} local nonempty = false for _, t in ipairs({"pres", "impf", "futr", "perf", "plup", "futp", "sigf"}) do			local row = {} local notempty = false

if data.forms[t .. "_" .. v .. "_indc"] then row = "\n! colspan=\"6\" style=\"background: #CCC\" |" .. data.forms[t .. "_" .. v .. "_indc"] nonempty = true notempty = true else for col, p in ipairs({"1s", "2s", "3s", "1p", "2p", "3p"}) do local slot = p .. "_" .. t .. "_" .. v .. "_indc" row[col] = "\n| " .. data.forms[slot] .. (						data.form_footnote_indices[slot] == nil and "" or						'' .. data.form_footnote_indices[slot].." "					)

-- show_form already called so can just check for "&mdash;" if data.forms[slot] ~= "&mdash;" then nonempty = true notempty = true end end

row = table.concat(row) end local fn			if t == "sigf" and data.form_footnote_indices["sigm"] then fn = '' .. data.form_footnote_indices["sigm"].." " else fn = "" end if notempty then table.insert(group, "\n! style=\"background:#c0cfe4\" | " .. tenses[t] .. fn .. row) end end

if nonempty and #group > 0 then table.insert(indc, "\n|- class=\"vsHide\"\n! rowspan=\"" .. tostring(#group) .. "\" style=\"background:#c0cfe4\" | " .. voices[v] .. "\n" .. table.concat(group, "\n|- class=\"vsHide\"")) end end

return [=[

! colspan="2" rowspan="2" style="background:#c0cfe4" | indicative ! colspan="3" style="background:#c0cfe4" | singular ! colspan="3" style="background:#c0cfe4" | plural ! style="background:#c0cfe4;width:12.5%" | first ! style="background:#c0cfe4;width:12.5%" | second ! style="background:#c0cfe4;width:12.5%" | third ! style="background:#c0cfe4;width:12.5%" | first ! style="background:#c0cfe4;width:12.5%" | second ! style="background:#c0cfe4;width:12.5%" | third ]=] .. table.concat(indc)
 * - class="vsHide"
 * - class="vsHide"

end

make_subj_rows = function(data) local subj = {}

for _, v in ipairs({"actv", "pasv"}) do		local group = {} local nonempty = false

for _, t in ipairs({"pres", "impf", "perf", "plup", "siga"}) do			local row = {} local notempty = false

if data.forms[t .. "_" .. v .. "_subj"] then row = "\n! colspan=\"6\" style=\"background: #CCC\" |" .. data.forms[t .. "_" .. v .. "_subj"] nonempty = true notempty = true else for col, p in ipairs({"1s", "2s", "3s", "1p", "2p", "3p"}) do local slot = p .. "_" .. t .. "_" .. v .. "_subj" row[col] = "\n| " .. data.forms[slot] .. (						data.form_footnote_indices[slot] == nil and "" or						'' .. data.form_footnote_indices[slot].." "					)

-- show_form already called so can just check for "&mdash;" if data.forms[slot] ~= "&mdash;" then nonempty = true notempty = true end end

row = table.concat(row) end local fn			if t == "siga" and data.form_footnote_indices["sigm"] then fn = '' .. data.form_footnote_indices["sigm"].." " else fn = "" end

if notempty then table.insert(group, "\n! style=\"background:#c0e4c0\" | " .. tenses[t] .. fn .. row) end end

if nonempty and #group > 0 then table.insert(subj, "\n|- class=\"vsHide\"\n! rowspan=\"" .. tostring(#group) .. "\" style=\"background:#c0e4c0\" | " .. voices[v] .. "\n" .. table.concat(group, "\n|- class=\"vsHide\"")) end end

return [=[

! colspan="2" rowspan="2" style="background:#c0e4c0" | subjunctive ! colspan="3" style="background:#c0e4c0" | singular ! colspan="3" style="background:#c0e4c0" | plural ! style="background:#c0e4c0;width:12.5%" | first ! style="background:#c0e4c0;width:12.5%" | second ! style="background:#c0e4c0;width:12.5%" | third ! style="background:#c0e4c0;width:12.5%" | first ! style="background:#c0e4c0;width:12.5%" | second ! style="background:#c0e4c0;width:12.5%" | third ]=] .. table.concat(subj)
 * - class="vsHide"
 * - class="vsHide"

end

make_impr_rows = function(data) local impr = {} local has_impr = false

for _, v in ipairs({"actv", "pasv"}) do		local group = {} local nonempty = false

for _, t in ipairs({"pres", "futr"}) do			local row = {}

if data.forms[t .. "_" .. v .. "_impr"] then row = "\n! colspan=\"6\" style=\"background: #CCC\" |" .. data.forms[t .. "_" .. v .. "_impr"] nonempty = true else for col, p in ipairs({"1s", "2s", "3s", "1p", "2p", "3p"}) do local slot = p .. "_" .. t .. "_" .. v .. "_impr" row[col] = "\n| " .. data.forms[slot] .. (						data.form_footnote_indices[slot] == nil and "" or						'' .. data.form_footnote_indices[slot].." "					)

-- show_form already called so can just check for "&mdash;" if data.forms[slot] ~= "&mdash;" then nonempty = true end end

row = table.concat(row) end

table.insert(group, "\n! style=\"background:#e4d4c0\" | " .. tenses[t] .. row) end

if nonempty and #group > 0 then has_impr = true table.insert(impr, "\n|- class=\"vsHide\"\n! rowspan=\"" .. tostring(#group) .. "\" style=\"background:#e4d4c0\" | " .. voices[v] .. "\n" .. table.concat(group, "\n|- class=\"vsHide\"")) end end

if not has_impr then return "" end return [=[

! colspan="2" rowspan="2" style="background:#e4d4c0" | imperative ! colspan="3" style="background:#e4d4c0" | singular ! colspan="3" style="background:#e4d4c0" | plural ! style="background:#e4d4c0;width:12.5%" | first ! style="background:#e4d4c0;width:12.5%" | second ! style="background:#e4d4c0;width:12.5%" | third ! style="background:#e4d4c0;width:12.5%" | first ! style="background:#e4d4c0;width:12.5%" | second ! style="background:#e4d4c0;width:12.5%" | third ]=] .. table.concat(impr) end
 * - class="vsHide"
 * - class="vsHide"

make_nonfin_rows = function(data) local nonfin = {}

for _, f in ipairs({"inf", "ptc"}) do		local row = {}

for col, t in ipairs({"pres_actv", "perf_actv", "futr_actv", "pres_pasv", "perf_pasv", "futr_pasv"}) do local slot = t .. "_" .. f --row[col] = "\n| " .. data.forms[slot] row[col] = "\n| " .. data.forms[slot] .. (				data.form_footnote_indices[slot] == nil and "" or				'' .. data.form_footnote_indices[slot] .." "			)

end

row = table.concat(row) table.insert(nonfin, "\n|- class=\"vsHide\"\n! style=\"background:#e2e4c0\" colspan=\"2\" | " .. nonfins[f] .. row) end

return [=[

! colspan="2" rowspan="2" style="background:#e2e4c0" | non-finite forms ! colspan="3" style="background:#e2e4c0" | active ! colspan="3" style="background:#e2e4c0" | passive ! style="background:#e2e4c0;width:12.5%" | present ! style="background:#e2e4c0;width:12.5%" | perfect ! style="background:#e2e4c0;width:12.5%" | future ! style="background:#e2e4c0;width:12.5%" | present ! style="background:#e2e4c0;width:12.5%" | perfect ! style="background:#e2e4c0;width:12.5%" | future ]=] .. table.concat(nonfin)
 * - class="vsHide"
 * - class="vsHide"

end

make_vn_rows = function(data) local vn = {} local has_vn = false

local row = {}

for col, slot in ipairs({"ger_gen", "ger_dat", "ger_acc", "ger_abl", "sup_acc", "sup_abl"}) do		-- show_form already called so can just check for "&mdash;" if data.forms[slot] ~= "&mdash;" then has_vn = true end row[col] = "\n| " .. data.forms[slot] .. (			data.form_footnote_indices[slot] == nil and "" or			'' .. data.form_footnote_indices[slot] .. " "		) end

row = table.concat(row)

if has_vn then table.insert(vn, "\n|- class=\"vsHide\"" .. row) end

if not has_vn then return "" end return [=[

! colspan="2" rowspan="3" style="background:#e0e0b0" | verbal nouns ! colspan="4" style="background:#e0e0b0" | gerund ! colspan="2" style="background:#e0e0b0" | supine ! style="background:#e0e0b0;width:12.5%" | genitive ! style="background:#e0e0b0;width:12.5%" | dative ! style="background:#e0e0b0;width:12.5%" | accusative ! style="background:#e0e0b0;width:12.5%" | ablative ! style="background:#e0e0b0;width:12.5%" | accusative ! style="background:#e0e0b0;width:12.5%" | ablative]=] .. table.concat(vn)
 * - class="vsHide"
 * - class="vsHide"

end

make_footnotes = function(data) local tbl = {} local i = 0 for k,v in pairs(data.footnotes) do		i = i + 1 tbl[i] = ''..tostring(k)..' '..v..' ' end return table.concat(tbl) end

override = function(data, args) for slot in iter_slots(true, false) do		if args[slot] then data.forms[slot] = split(args[slot], "/") end end end

checkexist = function(data) if NAMESPACE ~= '' then return end local outerbreak = false for _, conjugation in pairs(data.forms) do		if conjugation then if type(conjugation) == "string" then conjugation = {conjugation} end for _, conj in ipairs(conjugation) do				if not cfind(conj, " ") then local title = lang:makeEntryName(conj) local t = mw.title.new(title) if t and not t.exists then table.insert(data.categories, "Latin verbs with red links in their inflection tables") outerbreak = true break end end end end if outerbreak then break end end end

checkirregular = function(args,data) local apocopic = sub(args[1],1,-2) apocopic = gsub(apocopic,'[^aeiouyāēīōūȳ]+$','') if args[1] and args[2] and not find(args[2],'^'..apocopic) then table.insert(data.categories,'Latin stem-changing verbs') end end

-- functions for creating external search hyperlinks

flatten_values = function(T) function noaccents(x) return gsub(toNFD(x),'[^%w]+',"") end function cleanup(x) return noaccents(gsub(gsub(gsub(x, '%[', ), '%]', ), ' ', '+')) end local tbl = {} for _, v in pairs(T) do		if type(v) == "table" then local FT = flatten_values(v) for _, V in pairs(FT) do				tbl[#tbl+1] = cleanup(V) end else if find(v, '<') == nil then tbl[#tbl+1] = cleanup(v) end end end return tbl end

link_google_books = function(verb, forms, domain) function partition_XS_into_N(XS, N)		local count = 0 local mensae = {} for _, v in pairs(XS) do			if count % N == 0 then mensae[#mensae+1] = {} end count = count + 1 mensae[#mensae][#(mensae[#mensae])+1] = v end return mensae end function forms_N_to_link(fs, N, args, site) return '[https://www.google.com/search?'..args..'&q='..site..'+%22'.. table.concat(fs, "%22+OR+%22") ..'%22 '..N..']' end function make_links_txt(fs, N, site) local args = site == "Books" and "tbm=bks&lr=lang_la" or "" local links = {} for k,v in pairs(partition_XS_into_N(fs, N)) do			links[#links+1] = forms_N_to_link(v,k,args,site=="Books" and "" or site) end return table.concat(links, ' - ') end return "Google "..domain.." forms of "..verb.." : "..make_links_txt(forms, 30, domain) end

return export

-- For Vim, so we get 4-space tabs -- vim: set ts=4 sw=4 noet: