Module:la-verb
Appearance
- The following documentation is located at Module:la-verb/documentation. [edit] Categories were auto-generated by Module:module categorization. [edit]
- Useful links: subpage list • links • transclusions • testcases • sandbox
This module is used for the various Latin verb inflection tables.
-- 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
-- 8. Automatic forms of slots which depend on the values of other slots should take into account overrides on the other slot:
-- futr_actv_ptc: determines futr_actv_inf and perp_actv_inf
-- perf_pasv_ptc: determines perf_pasv_inf and futp_pasv_inf (all actv if deponent or semideponent)
-- acc_sup: determines futr_pasv_inf (and futr_actv_inf if there's no futr_pasv_ptc)
-- 9. Handle "revertor"-type: deponent in the present, but not in the perfect.
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local export = {}
local test_new_la_verb_module = false
local m_la_utilities = require("Module:la-utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local m_utilities = require("Module:utilities")
local lang = require("Module:languages").getByCode("la")
local sc = require("Module:scripts").getByCode("Latn")
local allowed_subtypes = mw.loadData("Module:la-verb/data").allowed_subtypes
local PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().namespace
if NAMESPACE == 118 then -- Reconstruction
PAGENAME = "*" .. PAGENAME
end
-- Conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local make_conjugation = {}
local add_form = m_la_utilities.add_form
local concat = table.concat
local contains = m_table.contains
local deep_equals = m_table.deepEquals
local flatten = m_table.flatten
local full_link = m_links.full_link
local insert = table.insert
local insert_if_not = m_table.insertIfNot
local ipairs = ipairs
local pairs = pairs
local pattern_escape = require("Module:string utilities").pattern_escape
local remove = table.remove
local remove_links = m_links.remove_links
local split = mw.text.split
local table_len = m_table.length
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local tostring = tostring
local type = type
local u = mw.ustring.char
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
local usub = mw.ustring.sub
local MACRON = u(0x304)
local BREVE = u(0x306)
local length_mark = "[" .. MACRON .. BREVE .. "]*"
local generic_slots = {}
local non_generic_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?
}
local function handle_person(t, v, mood)
local non_pers_slot = t .. "_" .. v .. "_" .. mood
insert(generic_slots, non_pers_slot)
for _, p in ipairs{"1s", "2s", "3s", "1p", "2p", "3p"} do
insert(non_generic_slots, p .. "_" .. non_pers_slot)
end
end
for _, v in ipairs{"actv", "pasv"} do
for _, t in ipairs{"pres", "impf", "futr", "perf", "plup", "futp", "sigf"} do
handle_person(t, v, "indc")
end
for _, t in ipairs{"pres", "impf", "perf", "plup", "siga"} do
handle_person(t, v, "subj")
end
for _, t in ipairs{"pres", "futr"} do
handle_person(t, v, "impr")
end
for _, f in ipairs{"inf", "ptc"} do
for _, t in ipairs{"pres", "futr", "perf", "futp", "perp"} do
insert(non_generic_slots, t .. "_" .. v .. "_" .. f)
end
end
end
insert(non_generic_slots, "sigm_actv_inf")
local ger_cases = {"gen", "dat", "acc", "abl"}
for _, c in ipairs(ger_cases) do
insert(non_generic_slots, c .. "_ger")
end
local sup_cases = {"acc", "abl"}
for _, c in ipairs(sup_cases) do
insert(non_generic_slots, c .. "_sup")
end
local function track(page)
require("Module:debug").track("la-verb/" .. page)
end
-- Constant version of :find()
local function cfind(str, text)
return str:find(text, nil, true)
end
local function make_link(page, display, face, accel)
return full_link({term = page, alt = display, lang = lang, sc = sc, accel = accel}, face)
end
local function normalize_form(form)
if type(form) == "table" and table_len(form) == 1 then
return form[1]
end
return form
end
local function form_is_empty(form)
form = normalize_form(form)
return not form or form == "" or form == "-" or form == "—" or form == "—"
end
-- 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 = table_len(non_generic_slots)
return function()
slotnum = slotnum + 1
if slotnum > max_slotnum then
slotnum = 1
stage = stage + 1
if stage == 2 then
if include_generic then
max_slotnum = table_len(generic_slots)
else
stage = stage + 1
end
end
if stage == 3 then
if include_linked then
max_slotnum = table_len(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]
end
return "linked_" .. potential_lemma_slots[slotnum]
end
end
local function ine(val)
if val == "" then
return nil
end
return val
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)
return deep_equals(normalize_form(form1), normalize_form(form2))
end
-- Construct a simple one- or two-part link, which will be put through full_link later.
local function make_raw_link(page, display)
if page and display then
return "[[" .. page .. "|" .. display .. "]]"
elseif page then
return "[[" .. page .. "]]"
end
return display
end
local function split_prefix_and_base(lemma, main_verbs)
for _, main in ipairs(main_verbs) do
local prefix = umatch(lemma, "^(.*)" .. pattern_escape(main) .. "$")
if prefix then
return prefix, main
end
end
error("Argument " .. lemma .. " doesn't end in any of " .. 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 cfind(ending, "(") then
return umatch(lemma, ending)
end
return umatch(lemma, "^(.*)" .. ending .. "$")
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]
local not_this_subtype = false
for _, subtype in ipairs(subtypes) do
-- A cancelled subtype will have the value false.
if specified_subtypes[subtype] == false 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",
["aijō"] = "3rd-io",
["ajō"] = "3rd-io",
["dīcō"] = "3rd",
["dūcō"] = "3rd",
["faciō"] = "3rd-io",
["fīō"] = "3rd",
["ferō"] = "3rd",
["inquam"] = "irreg",
["volō"] = "irreg",
["mālō"] = "irreg",
["nōlō"] = "irreg",
["possum"] = "irreg",
["sum"] = "irreg",
["edō"] = "3rd",
["dō"] = "1st",
["eō"] = "irreg",
}
local function detect_decl_and_subtypes(args)
local subtypes, specs = {}, split(args[1] or "", "%.")
local conj_arg = remove(specs, 1)
for _, spec in ipairs(specs) do
subtypes[spec:gsub("%-", "")] = spec:sub(1, 1) ~= "-"
end
local orig_lemma = (args[2] or PAGENAME):gsub("(%[%[.-)]]", "%1\255")
:gsub("([io])(\255?)$", "%1" .. MACRON .. "%2")
:gsub("\255", "]]")
orig_lemma = toNFC(orig_lemma)
local lemma = remove_links(orig_lemma)
local base, conjtype, conj_subtype, detected_subtypes
local base_conj_arg, auto_perf_supine = conj_arg:match("^([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 orig_lemma:sub(1, 1) == "-" then
subtypes.suffix = true
end
local auto_perf, auto_supine, auto_sigm
if subtypes.sigmpasv then
subtypes.sigm = true
end
if subtypes.sigm 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"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres 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
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"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
else
auto_perf = base .. "u"
auto_supine = base .. "it"
end
end
if auto_sigm then
auto_sigm = base .. "ēss"
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"}},
{"ī", {"nopres"}},
-- {"nopres", "impers"} not possible to auto-detect, as "it" is treated as {"impers"}
})
if subtypes.I then
conjtype = "3rd-io"
else
conjtype = "3rd"
end
end
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
end
if subtypes.suffix then
auto_perf = "-"
auto_supine = "-"
auto_sigm = "-"
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"}},
{"ī", {"nopres"}},
-- {"nopres", "impers"} not possible to auto-detect, as "it" is treated as {"impers"}
})
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres 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
elseif conj_arg == "irreg" then
conjtype = "irreg"
local prefix
prefix, base = split_prefix_and_base(lemma, {
"aiō",
"aiiō",
"aijō",
"ajō",
"dīcō",
"dūcō",
"faciō",
"fīō",
"ferō",
"inquam",
"volō",
"mālō",
"nōlō",
"possum",
-- 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] = lang:makeEntryName(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
elseif detected_subtype == "nopres" and subtypes.perfaspres then
-- perfaspres overrides nopres
else
subtypes[detected_subtype] = true
end
end
if subtypes.nopres or subtypes.perfaspres then
subtypes.noger = true
end
if conjtype ~= "irreg" then
args[1] = base
local perf_stem, supine_stem
if subtypes.depon or subtypes.semidepon or subtypes.nopres 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 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 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
if auto_sigm and subtypes.depon then
subtypes.sigmpasv = true
end
for subtype in pairs(subtypes) do
if (
subtype == "I" and conj_arg ~= "3" or
not allowed_subtypes[subtype]
) then
error("Unrecognized verb subtype " .. mw.dumpObject(subtype) .. " for this conjugation")
end
end
return conjtype, conj_subtype, subtypes, orig_lemma, lemma
end
local function form_contains(forms, form)
if forms == nil then
return
elseif type(forms) ~= "table" then
return forms == form
end
return contains(forms, form) and true or false
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(forms, keytype, stem, suf1s, suf2s, suf3s, suf1p, suf2p, suf3p)
add_form(forms, "1s_" .. keytype, stem, suf1s)
add_form(forms, "2s_" .. keytype, stem, suf2s)
add_form(forms, "3s_" .. keytype, stem, suf3s)
add_form(forms, "1p_" .. keytype, stem, suf1p)
add_form(forms, "2p_" .. keytype, stem, suf2p)
add_form(forms, "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(forms, keytype, stem, suf2s, suf2p)
add_form(forms, "2s_" .. keytype, stem, suf2s)
add_form(forms, "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(forms, keytype, stem, suf2s, suf3s, suf2p, suf3p)
add_form(forms, "2s_" .. keytype, stem, suf2s)
add_form(forms, "3s_" .. keytype, stem, suf3s)
add_form(forms, "2p_" .. keytype, stem, suf2p)
add_form(forms, "3p_" .. keytype, stem, suf3p)
end
local function make_perfect_passive(data)
local forms = data.forms
local ppp = forms["perf_pasv_ptc"]
if type(ppp) ~= "table" then
ppp = {ppp}
end
local ppplinks = {}
for _, pppform in ipairs(ppp) do
insert(ppplinks, make_link(pppform, nil, "term"))
end
local ppplink = concat(ppplinks, " or ")
local sumlink = make_link("sum", nil, "term")
local 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 passive_prefix, passive_suffix = data.passive_prefix, data.passive_suffix
local prefix_joiner = passive_prefix and passive_prefix:match(" $") and "+ " or ""
local suffix_joiner = passive_suffix and passive_suffix:match("^ ") and " +" or ""
for slot, text in pairs(text_for_slot) do
forms[slot] = (passive_prefix or "") .. prefix_joiner .. ppplink .. " + " ..
text .. " of " .. sumlink .. suffix_joiner .. (passive_suffix or "")
end
ppp = 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
insert(ppplinks, make_link(pppform, nil, "term"))
end
ppplink = concat(ppplinks, " or ")
sumlink = make_link("sum", nil, "term")
for slot, text in pairs(text_for_slot) do
forms[slot] = forms[slot] .. " or " .. ppplink .. " + " .. text .. " of " .. sumlink
end
end
end
local function handle_deponent(data, subtypes)
local forms = data.forms
-- Generate a list of form types to remove.
local to_remove = {"pres_pasv_ptc", "futr_pasv_inf"}
if subtypes.depon then
insert(to_remove, "actv")
else
insert(to_remove, "pres_pasv")
insert(to_remove, "impf_pasv")
insert(to_remove, "futr_pasv")
if subtypes.semidepon then
insert(to_remove, "perf_actv")
insert(to_remove, "plup_actv")
insert(to_remove, "futp_actv")
end
end
-- Remove forms.
for slot in pairs(forms) do
if not (
slot == "futr_actv_inf" or
slot == "perp_actv_inf" or
slot == "pres_actv_ptc" or
slot == "futr_actv_ptc" or
slot == "futr_pasv_ptc"
) then
for _, part in ipairs(to_remove) do
if cfind(slot, part) then
forms[slot] = nil
break
end
end
end
end
-- Change passive to active, except for the future passive participle.
local changes = {}
for slot in pairs(forms) do
if cfind(slot, "pasv") and slot ~= "futr_pasv_ptc" then
changes[slot] = slot:gsub("pasv", "actv")
end
end
for old, new in pairs(changes) do
add_form(forms, new, "", forms[old])
forms[old] = nil
end
end
local function add_sync_perf(data, form, suf, note, noteindex)
local forms = data.forms
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local i = 0
while true do
i = i + 1
local stem = formval[i]
if not stem then
break
end
stem = stem:match("^(.*)" .. pattern_escape(suf) .. "$")
-- Can only syncopate "vi", "ve", "vē", or any one of them spelled with a "u" after a vowel.
if stem then
local new_stem = toNFD(stem)
local vowel, loc, v, ei, diacritic = umatch(new_stem, "([aeiouyAEIOUY]?)" .. length_mark .. "()([uv])([ei])(" .. length_mark .. ")$")
if loc and (v == "v" or vowel ~= "") and (ei == "e" or diacritic == "" or cfind(diacritic, BREVE)) then
new_stem = usub(new_stem, 1, loc - 1)
-- Can't be omitted if it's part of the first syllable.
if new_stem:match("[aeiouyAEIOUY]") then
i = i + 1
add_form(forms, form, new_stem, suf, i)
data.form_footnote_indices[form] = tostring(noteindex)
data.footnotes[noteindex] = note
end
end
end
end
end
local function has_no_gerund(forms)
if not form_is_empty(forms["futr_pasv_ptc"]) then
return false
end
for _, case in ipairs(ger_cases) do
if not form_is_empty(forms[case .. "_ger"]) then
return false
end
end
return true
end
local function postprocess(data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
local subtypes = typeinfo.subtypes
if subtypes.nopres or subtypes.perfaspres then
insert_if_not(title, "no [[present tense|present]] stem")
insert_if_not(categories, "Latin verbs with missing present stem")
insert_if_not(categories, "Latin defective verbs")
end
-- 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 subtypes.nosup then
-- Some verbs have no supine forms or forms derived from the supine
insert_if_not(title, "no [[supine tense|supine]] stem")
insert_if_not(categories, "Latin verbs with missing supine stem")
insert_if_not(categories, "Latin defective verbs")
forms["futr_actv_inf"] = nil
forms["futr_actv_ptc"] = nil
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
elseif subtypes.nosupfutractv then
-- Some verbs have a missing future active participle
insert_if_not(title, "no [[future tense|future]] [[active voice|active]] [[participle]]")
insert_if_not(categories, "Latin verbs with supine stem with missing future active participle")
insert_if_not(categories, "Latin defective verbs")
forms["futr_actv_ptc"] = nil
forms["perp_actv_inf"] = nil
elseif subtypes.supfutractvonly then
-- Some verbs have no supine forms or forms derived from the supine,
-- except for the future active infinitive/participle
insert_if_not(title, "no [[supine tense|supine]] stem except in the [[future tense|future]] [[active voice|active]] [[participle]]")
insert_if_not(categories, "Latin verbs with missing supine stem except in the future active participle")
insert_if_not(categories, "Latin defective verbs")
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
end
-- Add information for the passive perfective forms
if not (
form_is_empty(forms["perf_pasv_ptc"]) or
subtypes.optsemidepon or
subtypes.impers or
subtypes.passimpers or
subtypes["3only"] or
subtypes.pass3only
) then
make_perfect_passive(data)
end
-- Perfect forms as present tense.
if subtypes.perfaspres then
insert_if_not(title, "[[active voice|active]]-only")
insert_if_not(title, "[[perfect tense|perfect]] forms as [[present tense|present]]")
insert_if_not(title, "[[pluperfect tense|pluperfect]] as [[imperfect tense|imperfect]]")
insert_if_not(title, "[[future perfect]] as [[future tense|future]]")
insert_if_not(categories, "Latin active-only verbs")
insert_if_not(categories, "Latin verbs with perfect forms used in the present tense")
if not (subtypes.nosup or subtypes.supfutractvonly) then
insert_if_not(title, "otherwise [[semi-deponent]]")
insert_if_not(categories, "Latin semi-deponent verbs")
end
-- Remove present active, imperfect active and future active forms and passive forms.
-- Change perfect forms to non-perfect forms.
local new_forms = {}
forms["futr_pasv_inf"] = nil
for slot, form in pairs(forms) do
if not (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
-- Only convert the future passive infinitive to active if there's no future active infinitive already.
if cfind(slot, "pasv") then
slot = slot:gsub("pasv", "actv")
else
slot = slot:gsub("perf", "pres")
:gsub("plup", "impf")
:gsub("futp", "futr")
end
new_forms[slot] = form
end
end
data.forms, forms = new_forms, new_forms
-- No present stem.
elseif subtypes.nopres then
for slot in pairs(forms) do
if (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
forms[slot] = nil
end
end
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 subtypes.impers then
-- Impersonal verbs have only third-person singular forms.
insert_if_not(title, "[[impersonal verb|impersonal]]")
insert_if_not(categories, "Latin impersonal verbs")
-- Remove all non-3sg forms
for slot in pairs(forms) do
if slot:match("[12][sp]") or slot:match("3p") then
forms[slot] = nil
end
end
elseif subtypes["3only"] then
insert_if_not(title, "[[third person]]-only")
insert_if_not(categories, "Latin third-person-only verbs")
-- Remove all non-3sg forms
for slot in pairs(forms) do
if slot:match("[12][sp]") then
forms[slot] = nil
end
end
end
if subtypes.nopasvperf and not subtypes.nosup and not 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.
insert_if_not(title, "no [[passive voice|passive]] [[perfect tense|perfect]] forms")
insert_if_not(categories, "Latin defective verbs")
-- Remove all passive perfect forms
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
cfind(slot, "perf") or
cfind(slot, "plup") or
cfind(slot, "futp")
) then
forms[slot] = nil
end
end
end
-- Deponent verbs use passive forms with active meaning.
if subtypes.depon then
insert_if_not(title, "[[deponent]]")
insert_if_not(categories, "Latin deponent verbs")
handle_deponent(data, subtypes)
-- Semi-deponent verbs use perfective passive forms with active meaning,
-- and have no imperfective passive.
elseif subtypes.semidepon then
insert_if_not(title, "[[semi-deponent]]")
insert_if_not(categories, "Latin semi-deponent verbs")
handle_deponent(data, subtypes)
-- 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.
elseif subtypes.optsemidepon then
insert_if_not(title, "optionally [[semi-deponent]]")
insert_if_not(categories, "Latin semi-deponent verbs")
insert_if_not(categories, "Latin optionally semi-deponent verbs")
handle_deponent(data, subtypes)
elseif subtypes.noperf then
-- Some verbs have no perfect stem (e.g. inalbēscō, -ěre)
insert_if_not(title, "no [[perfect tense|perfect]] stem")
insert_if_not(categories, "Latin defective verbs")
if not subtypes.depon then
insert_if_not(categories, "Latin verbs with missing perfect stem")
end
-- Remove all active perfect forms (passive perfect forms may
-- still exist as they are formed with the supine stem)
for slot in pairs(forms) do
if cfind(slot, "actv") and (
cfind(slot, "perf") or
cfind(slot, "plup") or
cfind(slot, "futp")
) and slot ~= "futp_actv_inf" then
forms[slot] = nil
end
end
end
if subtypes.nopass then
-- Remove all passive forms
insert_if_not(title, "[[active voice|active]]-only")
insert_if_not(categories, "Latin active-only verbs")
-- Remove all non-3sg and passive forms
for slot in pairs(forms) do
if cfind(slot, "pasv") then
forms[slot] = nil
end
end
elseif subtypes.pass3only then
-- Some verbs have only third-person forms in the passive
insert_if_not(title, "only third-person forms in the [[passive voice|passive]]")
insert_if_not(categories, "Latin verbs with third-person passive")
-- Remove all non-3rd-person passive forms.
-- For phrasal verbs with a plural complement, also need to erase the
-- 3s forms.
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
(subtypes.mp or subtypes.fp or subtypes.np) and slot:find("3s")
) then
forms[slot] = nil
end
end
elseif subtypes.passimpers then
-- Some verbs are impersonal in the passive
local title_msg = "[[impersonal verb|impersonal]] in the [[passive voice|passive]]"
if subtypes.passimpersold then
title_msg = title_msg .. " in [[Old Latin]]"
end
insert_if_not(title, title_msg)
insert_if_not(categories, "Latin verbs with impersonal passive")
-- Remove all non-3sg passive forms
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
slot:find("3p")
) then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the imperative
if subtypes.noimp then
-- Some verbs have no imperatives
insert_if_not(title, "no [[imperative mood|imperative]]s")
insert_if_not(categories, "Latin verbs with missing imperative")
insert_if_not(categories, "Latin defective verbs")
-- Remove all imperative forms
for slot in pairs(forms) do
if cfind(slot, "impr") then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the future
if subtypes.nofut then
-- Some verbs (e.g. soleō) have no future
insert_if_not(title, "no [[future tense|future]]")
insert_if_not(categories, "Latin verbs with missing future")
insert_if_not(categories, "Latin defective verbs")
-- Remove all future forms
for slot in pairs(forms) do
if cfind(slot, "fut") then -- handles futr = future and futp = future perfect
forms[slot] = nil
end
end
end
local pres_stem = typeinfo.pres_stem
-- Add the ancient future_passive_participle of certain verbs
-- if pres_stem == "lāb" then
-- forms["futr_pasv_ptc"] = "lābundus"
-- elseif pres_stem == "collāb" then
-- forms["futr_pasv_ptc"] = "collābundus"
-- elseif pres_stem == "illāb" then
-- forms["futr_pasv_ptc"] = "illābundus"
-- elseif pres_stem == "relāb" then
-- forms["futr_pasv_ptc"] = "relābundus"
-- end
-- Add the poetic present passive infinitive forms of certain verbs
if subtypes.p3inf then
local form = "pres_" .. (subtypes.depon and "actv" or "pasv") .. "_inf"
local noteindex = table_len(data.footnotes) + 1
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
for i = 1, table_len(formval) do
insert(formval, usub(formval[i], 1, -2) .. "ier")
end
forms[form] = formval
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
--[==[
if subtypes.old2sgimp then
local form = "2s_pres_" .. (subtypes.depon and "actv" or "pasv") .. "_impr"
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local newvals = mw.clone(formval)
end]==]
-- Add the syncopated perfect forms, omitting the separately handled fourth conjugation cases.
if subtypes.poetsyncperf then
local noteindex, note = table_len(data.footnotes) + 1
if pres_stem and pres_stem:match("nōsc$") then
note = 'The verb "nōscō" and its compounds frequently drop the syllables "vi" and "ve" from their perfect, pluperfect and future perfect conjugations.'
else
note = "At least one rare poetic syncopated perfect form is attested."
end
-- infinitive
add_sync_perf(data, "perf_actv_inf", "sse", note, noteindex)
-- perfect actives
add_sync_perf(data, "2s_perf_actv_indc", "stī", note, noteindex)
add_sync_perf(data, "3s_perf_actv_indc", "t", note, noteindex)
add_sync_perf(data, "1p_perf_actv_indc", "mus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_indc", "stis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_indc", "runt", note, noteindex)
-- pluperfect actives
add_sync_perf(data, "1s_plup_actv_indc", "ram", note, noteindex)
add_sync_perf(data, "2s_plup_actv_indc", "rās", note, noteindex)
add_sync_perf(data, "3s_plup_actv_indc", "rat", note, noteindex)
add_sync_perf(data, "1p_plup_actv_indc", "rāmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_indc", "rātis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_indc", "rant", note, noteindex)
-- future perfect actives
add_sync_perf(data, "1s_futp_actv_indc", "rō", note, noteindex)
add_sync_perf(data, "2s_futp_actv_indc", "ris", note, noteindex)
add_sync_perf(data, "3s_futp_actv_indc", "rit", note, noteindex)
add_sync_perf(data, "1p_futp_actv_indc", "rimus", note, noteindex)
add_sync_perf(data, "2p_futp_actv_indc", "ritis", note, noteindex)
add_sync_perf(data, "3p_futp_actv_indc", "rint", note, noteindex)
-- perfect subjunctives
add_sync_perf(data, "1s_perf_actv_subj", "rim", note, noteindex)
add_sync_perf(data, "2s_perf_actv_subj", "rīs", note, noteindex)
add_sync_perf(data, "3s_perf_actv_subj", "rit", note, noteindex)
add_sync_perf(data, "1p_perf_actv_subj", "rīmus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_subj", "rītis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_subj", "rint", note, noteindex)
-- pluperfect subjunctives
add_sync_perf(data, "1s_plup_actv_subj", "ssem", note, noteindex)
add_sync_perf(data, "2s_plup_actv_subj", "ssēs", note, noteindex)
add_sync_perf(data, "3s_plup_actv_subj", "sset", note, noteindex)
add_sync_perf(data, "1p_plup_actv_subj", "ssēmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_subj", "ssētis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_subj", "ssent", note, noteindex)
end
-- Add category for sigmatic forms
if subtypes.sigm then
insert_if_not(categories, "Latin verbs with sigmatic forms")
-- Add subcategory for (very rare) passive sigmatic forms
if subtypes.sigmpasv then
insert_if_not(categories, "Latin verbs with passive sigmatic forms")
end
end
if subtypes.noger then
-- Some verbs (e.g. libet) have no gerund
forms["futr_pasv_ptc"] = nil
for _, case in ipairs(ger_cases) do
forms[case .. "_ger"] = nil
end
end
-- Catch verbs which don't have .noger explicitly specified.
if has_no_gerund(forms) then
if not (subtypes.nopres or subtypes.perfaspres) then
insert_if_not(title, "no [[gerund]]")
end
insert_if_not(categories, "Latin verbs with missing gerund")
insert_if_not(categories, "Latin defective verbs")
end
end
local function override(data, args)
local forms = data.forms
for slot in iter_slots(true, false) do
if args[slot] then
forms[slot] = split(args[slot], "/")
end
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).
local forms = data.forms
for _, slot in ipairs(potential_lemma_slots) do
local formval = forms[slot]
local linked_forms = {}
if formval then
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form == typeinfo.lemma then
insert(linked_forms, typeinfo.orig_lemma)
else
insert(linked_forms, form)
end
end
end
forms["linked_" .. slot] = linked_forms
end
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)
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 = remove_links(active_prefix)
local passive_prefix_no_links = remove_links(passive_prefix)
local plural_prefix_no_links = remove_links(plural_prefix)
local plural_passive_prefix_no_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 = remove_links(active_suffix)
local passive_suffix_no_links = remove_links(passive_suffix)
local plural_suffix_no_links = remove_links(plural_suffix)
local plural_passive_suffix_no_links = remove_links(plural_passive_suffix)
local forms = data.forms
for slot in iter_slots(false, true) do
if not slot:match("_ger$") then
local prefix, suffix, prefix_no_links, suffix_no_links
if cfind(slot, "pasv") and slot:match("[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 cfind(slot, "pasv") and not cfind(slot, "_inf") then
prefix = passive_prefix
suffix = passive_suffix
prefix_no_links = passive_prefix_no_links
suffix_no_links = passive_suffix_no_links
elseif slot:match("[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 formval = forms[slot]
if not form_is_empty(formval) then
local affixed_forms = {}
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form_is_empty(form) then
insert(affixed_forms, form)
elseif slot:match("^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:match("[[%]]") then
form = "[[" .. form .. "]]"
end
insert(affixed_forms, prefix .. form .. suffix)
elseif form:match("[[%]]") 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).
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.
insert(affixed_forms, prefix_no_links .. form .. suffix_no_links)
end
end
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 Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|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 Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|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\"), which is not attested in the plural for any verb."
elseif note == "sigmdepon" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|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 (which is not attested in the plural for any verb)."
elseif note then
data.footnotes[n] = note
end
end
if args["notes"] == "-" then
data.footnotes = {}
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
v = v:gsub("|", "<!>")
:gsub("=", "<->")
:gsub(",", "<.>")
insert(ins_form, v)
end
end
if #ins_form > 0 then
insert(ins_text, key .. "=" .. concat(ins_form, ","))
end
end
if include_props then
insert(ins_text, "conj_type=" .. typeinfo.conj_type)
if typeinfo.conj_subtype then
insert(ins_text, "conj_subtype=" .. typeinfo.conj_subtype)
end
local subtypes = {}
for subtype in pairs(typeinfo.subtypes) do
insert(subtypes, subtype)
end
insert(ins_text, "subtypes=" .. concat(subtypes, "."))
end
return 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
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] = true,
[4] = true,
[5] = true,
prefix = true,
passive_prefix = true,
plural_prefix = true,
plural_passive_prefix = true,
gen_prefix = true,
dat_prefix = true,
acc_prefix = true,
abl_prefix = true,
suffix = true,
passive_suffix = true,
plural_suffix = true,
plural_passive_suffix = true,
gen_suffix = true,
dat_suffix = true,
acc_suffix = true,
abl_suffix = true,
label = true,
note1= true,
note2= true,
note3= true,
notes= true,
-- examined directly in export.show()
search = true
}
for slot in iter_slots(true, false) do
params[slot] = true
end
if from_headword then
local list = {list = true}
params.lemma = list
params.id = true
params.cat = list
end
local args = require("Module:parameters").process(parent_args, params)
local conj_type, conj_subtype, subtypes, orig_lemma, lemma =
detect_decl_and_subtypes(args)
if not make_conjugation[conj_type] then
error("Unknown conjugation type '" .. conj_type .. "'")
end
local data = {
forms = {},
title = {},
categories = args.cat and m_table.deepCopy(args.cat) or {},
form_footnote_indices = {},
footnotes = {},
id = args.id,
overriding_lemma = args.lemma,
} -- note: the addition of red superscripted footnotes ('<sup class="roa-red-superscript">' ... </sup>) 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 not args.prefix then
if args.passive_prefix then
error("Can't specify passive_prefix= without prefix=")
elseif args.plural_prefix then
error("Can't specify plural_prefix= without prefix=")
elseif args.plural_passive_prefix then
error("Can't specify plural_passive_prefix= without prefix=")
end
end
if not args.suffix then
if args.passive_suffix then
error("Can't specify passive_suffix= without suffix=")
elseif args.plural_suffix then
error("Can't specify plural_suffix= without suffix=")
elseif args.plural_passive_suffix then
error("Can't specify plural_passive_suffix= without suffix=")
end
end
local function normalize_prefix(prefix)
if not prefix then
return nil
end
local no_space_prefix = prefix:match("(.*)_$")
if no_space_prefix then
return no_space_prefix
elseif prefix:sub(-1) == "-" then
return prefix
else
return prefix .. " "
end
end
local function normalize_suffix(suffix)
if not suffix then
return nil
end
local no_space_suffix = suffix:match("^_(.*)$")
if no_space_suffix then
return no_space_suffix
elseif suffix:sub(1, 1) == "-" 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
make_conjugation(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
insert_if_not(data.title, args["label"])
end
notes_override(data, args)
return data, typeinfo
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_FUTR_PASV_PTC means to skip generating
-- the future passive participle.
local function make_gerund(data, typeinfo, base, und_variant, no_futr_pasv_ptc)
local subtypes = typeinfo.subtypes
if subtypes.noger then
return
end
local neut_endings = {
nom = "um",
gen = "ī",
dat = "ō",
acc = "um",
abl = "ō",
}
local endings
if subtypes.f then
endings = {
nom = "a",
gen = "ae",
dat = "ae",
acc = "am",
abl = "ā",
}
elseif subtypes.n then
endings = neut_endings
elseif subtypes.mp then
endings = {
nom = "ī",
gen = "ōrum",
dat = "īs",
acc = "ōs",
abl = "īs",
}
elseif subtypes.fp then
endings = {
nom = "ae",
gen = "ārum",
dat = "īs",
acc = "ās",
abl = "īs",
}
elseif 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 subtypes.nound or base:match("[vV]end$") or umatch(base, "[uU]" .. length_mark .. "end$") 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 forms = data.forms
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 subtypes.passimpers then
ending = "um"
end
add_form(forms, "futr_pasv_ptc", "", base .. ending)
if und_base then
add_form(forms, "futr_pasv_ptc", "", und_base .. ending)
end
end
elseif data[case .. "_prefix"] or data[case .. "_suffix"] then
add_form(forms, case .. "_ger", "", (data[case .. "_prefix"] or "")
.. base .. ending .. (data[case .. "_suffix"] or ""))
if und_base then
add_form(forms, case .. "_ger", "", (data[case .. "_prefix"] or "")
.. und_base .. ending .. (data[case .. "_suffix"] or ""))
end
end
end
for case, ending in pairs(neut_endings) do
add_form(forms, case .. "_ger", "",
(data.prefix or "") .. base .. ending .. (data.suffix or ""))
end
end
-- Conjugation functions
local function get_regular_stems(args, typeinfo)
local subtypes = typeinfo.subtypes
-- Get the parameters
if subtypes.depon or 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 subtypes.nopres or 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 subtypes.sigm then
typeinfo.sigm_stem = ine(args[5])
end
-- Prepare stems
if not (typeinfo.pres_stem or NAMESPACE == 10 or subtypes.nopres or subtypes.perfaspres) then -- Template:
error("Present stem has not been provided")
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 set_conj_categories(ord, data, typeinfo)
local categories = data.categories
local subtypes = typeinfo.subtypes
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs")
if subtypes.depon then
insert_if_not(categories, "Latin " .. ord .. " conjugation deponent verbs")
end
if subtypes.noperf then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing perfect stem")
end
if subtypes.nosup then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem")
elseif subtypes.supfutractvonly then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem except in the future active participle ")
end
local pres_stem = typeinfo.pres_stem
if not pres_stem then
return
end
pres_stem = pres_stem and pres_stem:gsub("[Qq]u", "\1")
for _, perf_stem in ipairs(typeinfo.perf_stem) do
perf_stem = perf_stem:gsub("[Qq]u", "\1")
if perf_stem == pres_stem .. "āv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -āv-")
elseif perf_stem == pres_stem .. "ēv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -ēv-")
elseif perf_stem == pres_stem .. "īv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -īv-")
elseif perf_stem == pres_stem .. "i" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -i-")
elseif perf_stem == pres_stem .. "u" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -u-")
elseif perf_stem == pres_stem then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with suffixless perfect")
elseif perf_stem:match("[sx]$") then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -s- or -x-")
else
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with irregular perfect")
end
end
end
-- Form-generating functions
local make_pres = {}
make_pres["1st"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_actv_indc", pres_stem, "ābam", "ābās", "ābat", "ābāmus", "ābātis", "ābant")
add_forms(forms, "futr_actv_indc", pres_stem, "ābō", "ābis", "ābit", "ābimus", "ābitis", "ābunt")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ābar", {"ābāris", "ābāre"}, "ābātur", "ābāmur", "ābāminī", "ābantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ābor", {"āberis", "ābere"}, "ābitur", "ābimur", "ābiminī", "ābuntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "em", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_subj", pres_stem, "ārem", "ārēs", "āret", "ārēmus", "ārētis", "ārent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "er", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_subj", pres_stem, "ārer", {"ārēris", "ārēre"}, "ārētur", "ārēmur", "ārēminī", "ārentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ā", "āte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ātō", "ātō", "ātōte", "antō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "āre", "āminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ātor", "ātor", nil, "antor")
-- Present infinitives
forms["pres_actv_inf"] = pres_stem .. "āre"
forms["pres_pasv_inf"] = pres_stem .. "ārī"
-- Imperfective participles
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)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "eō", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "ēbō", "ēbis", "ēbit", "ēbimus", "ēbitis", "ēbunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", pres_stem, "ērem", "ērēs", "ēret", "ērēmus", "ērētis", "ērent")
-- Active imperative
if not noimpr then
add_2_forms(forms, "pres_actv_impr", pres_stem, "ē", "ēte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ētō", "ētō", "ētōte", "entō")
end
if not nopass then
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "eor", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ēbor", {"ēberis", "ēbere"}, "ēbitur", "ēbimur", "ēbiminī", "ēbuntur")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "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(forms, "pres_pasv_impr", pres_stem, "ēre", "ēminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ētor", "ētor", nil, "entor")
end
end
-- Present infinitives
forms["pres_actv_inf"] = pres_stem .. "ēre"
if not nopass then
forms["pres_pasv_inf"] = pres_stem .. "ērī"
end
-- Imperfective participles
forms["pres_actv_ptc"] = pres_stem .. "ēns"
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "end", nil, nopass)
end
make_pres["3rd"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "is", "it", "imus", "itis", "unt")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {"eris", "ere"}, "itur", "imur", "iminī", "untur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ar", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ar", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "untō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "untor")
-- Present infinitives
forms["pres_actv_inf"] = pres_stem .. "ere"
forms["pres_pasv_inf"] = pres_stem .. "ī"
-- Imperfective participles
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)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "is", "it", "imus", "itis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "iuntō")
-- Passive imperfective indicative
if not nopass then
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"eris", "ere"}, "itur", "imur", "iminī", "iuntur")
add_forms(forms, "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(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "iuntor")
end
-- Present infinitives
forms["pres_actv_inf"] = pres_stem .. "ere"
if not nopass then
forms["pres_pasv_inf"] = pres_stem .. "ī"
end
-- Imperfective participles
forms["pres_actv_ptc"] = pres_stem .. "iēns"
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant", nopass)
end
make_pres["4th"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "īs", "it", "īmus", "ītis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"īris", "īre"}, "ītur", "īmur", "īminī", "iuntur")
add_forms(forms, "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(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ītō", "ītō", "ītōte", "iuntō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ītor", "ītor", nil, "iuntor")
-- Present infinitives
forms["pres_actv_inf"] = pres_stem .. "īre"
forms["pres_pasv_inf"] = pres_stem .. "īrī"
-- Imperfective participles
forms["pres_actv_ptc"] = pres_stem .. "iēns"
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
local make_pres_mt = {}
function make_pres_mt:__call(conj, data, typeinfo, pres_stem, ...)
if not pres_stem then
return
end
return self[conj](data, typeinfo, pres_stem, ...)
end
setmetatable(make_pres, make_pres_mt)
local function make_perf(data, perf_stem, no_inf)
if not perf_stem then
return
end
local forms = data.forms
if type(perf_stem) ~= "table" then
perf_stem = {perf_stem}
end
for _, stem in ipairs(perf_stem) do
-- Perfective indicative
add_forms(forms, "perf_actv_indc", stem, "ī", "istī", "it", "imus", "istis", {"ērunt", "ēre"})
add_forms(forms, "plup_actv_indc", stem, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futp_actv_indc", stem, "erō", "eris", "erit", "erimus", "eritis", "erint")
-- Perfective subjunctive
add_forms(forms, "perf_actv_subj", stem, "erim", "erīs", "erit", "erīmus", "erītis", "erint")
add_forms(forms, "plup_actv_subj", stem, "issem", "issēs", "isset", "issēmus", "issētis", "issent")
-- Perfect infinitive
if not no_inf then
add_form(forms, "perf_actv_inf", stem, "isse")
end
end
end
local function make_supine(data, typeinfo, supine_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or not supine_stem then
return
end
local forms = data.forms
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, futr_actv_ptc, perp_actv_inf, perf_pasv_inf, perf_pasv_ptc, futr_pasv_inf, futp_pasv_inf
local perf_pasv_ptc_lemma, perf_pasv_ptc_acc, perf_pasv_ptc_nom_sg, perf_pasv_ptc_nom_pl
-- Perfect/future participles
if stem:match("mortu$") then -- Exceptions
futr_actv_ptc = stem:gsub("mortu$", "moritūrus")
elseif stem:match("ort$") then
futr_actv_ptc = stem:gsub("ort$", "oritūrus")
else
futr_actv_ptc = stem .. "ūrus"
end
local impers = (
subtypes.impers or
subtypes.passimpers and not (subtypes.depon or subtypes.semidepon or subtypes.optsemidepon)
)
perf_pasv_ptc_lemma = stem .. "us"
if subtypes.n or impers then
perf_pasv_ptc = stem .. "um"
perf_pasv_ptc_acc = perf_pasv_ptc
perf_pasv_ptc_nom_sg = perf_pasv_ptc
perf_pasv_ptc_nom_pl = stem .. "a"
if impers then
perf_pasv_ptc_lemma = perf_pasv_ptc
end
elseif subtypes.mp then
perf_pasv_ptc = stem .. "ī"
perf_pasv_ptc_acc = stem .. "ōs"
perf_pasv_ptc_nom_pl = perf_pasv_ptc
elseif subtypes.fp then
perf_pasv_ptc = stem .. "ae"
perf_pasv_ptc_acc = stem .. "ās"
perf_pasv_ptc_nom_pl = perf_pasv_ptc
elseif subtypes.np then
perf_pasv_ptc = stem .. "a"
perf_pasv_ptc_acc = perf_pasv_ptc
perf_pasv_ptc_nom_pl = perf_pasv_ptc
elseif subtypes.f then
perf_pasv_ptc = stem .. "a"
perf_pasv_ptc_acc = stem .. "am"
perf_pasv_ptc_nom_sg = perf_pasv_ptc
perf_pasv_ptc_nom_pl = stem .. "ae"
else
perf_pasv_ptc = perf_pasv_ptc_lemma
perf_pasv_ptc_acc = stem .. "um"
perf_pasv_ptc_nom_sg = perf_pasv_ptc
perf_pasv_ptc_nom_pl = stem .. "ī"
end
perf_pasv_ptc_acc = make_raw_link(perf_pasv_ptc_lemma, perf_pasv_ptc_acc ~= perf_pasv_ptc_lemma and perf_pasv_ptc_acc or nil)
perf_pasv_inf = perf_pasv_ptc_acc .. " [[esse]]"
futr_pasv_inf = make_raw_link(stem .. "um") .. " [[īrī]]"
futp_pasv_inf = perf_pasv_ptc_acc .. " [[fore]]"
if subtypes.nosupfutractv then
futr_actv_inf = make_raw_link(stem .. "um") .. " [[īre]]"
else
local futr_actv_ptc_acc = futr_actv_ptc:gsub("us$", "um")
futr_actv_inf = make_raw_link(futr_actv_ptc, futr_actv_ptc_acc) .. " [[esse]]"
perp_actv_inf = make_raw_link(futr_actv_ptc, futr_actv_ptc_acc) .. " [[fuisse]]"
end
add_form(forms, "futr_actv_inf", "", futr_actv_inf)
add_form(forms, "futr_actv_ptc", "", futr_actv_ptc)
add_form(forms, "perp_actv_inf", "", perp_actv_inf)
add_form(forms, "perf_pasv_inf", "", perf_pasv_inf)
add_form(forms, "perf_pasv_ptc", "", perf_pasv_ptc)
add_form(forms, "futr_pasv_inf", "", futr_pasv_inf)
add_form(forms, "futp_pasv_inf", "", futp_pasv_inf)
-- Supine itself
add_form(forms, "acc_sup", stem, "um")
add_form(forms, "abl_sup", stem, "ū")
if not subtypes.supfutractvonly then
if perf_pasv_ptc_nom_sg then
perf_pasv_ptc_nom_sg = "[[" .. perf_pasv_ptc_nom_sg .. "]] "
add_forms(forms, "perf_pasv_indc", perf_pasv_ptc_nom_sg, "[[sum]]", "[[es]]", "[[est]]", nil, nil, nil)
add_forms(forms, "plup_pasv_indc", perf_pasv_ptc_nom_sg, "[[eram]]", "[[erās]]", "[[erat]]", nil, nil, nil)
add_forms(forms, "futp_pasv_indc", perf_pasv_ptc_nom_sg, "[[erō]]", "[[eris]]", "[[erit]]", nil, nil, nil)
add_forms(forms, "perf_pasv_subj", perf_pasv_ptc_nom_sg, "[[sim]]", "[[sīs]]", "[[sit]]", nil, nil, nil)
add_forms(forms, "plup_pasv_subj", perf_pasv_ptc_nom_sg, "[[essem]]", "[[essēs]]", "[[esset]]", nil, nil, nil)
end
if perf_pasv_ptc_nom_pl then
perf_pasv_ptc_nom_pl = "[[" .. perf_pasv_ptc_nom_pl .. "]] "
add_forms(forms, "perf_pasv_indc", perf_pasv_ptc_nom_pl, nil, nil, nil, "[[sumus]]", "[[estis]]", "[[sunt]]")
add_forms(forms, "plup_pasv_indc", perf_pasv_ptc_nom_pl, nil, nil, nil, "[[erāmus]]", "[[erātis]]", "[[erant]]")
add_forms(forms, "futp_pasv_indc", perf_pasv_ptc_nom_pl, nil, nil, nil, "[[erimus]]", "[[eritis]]", "[[erint]]")
add_forms(forms, "perf_pasv_subj", perf_pasv_ptc_nom_pl, nil, nil, nil, "[[sīmus]]", "[[sītis]]", "[[sint]]")
add_forms(forms, "plup_pasv_subj", perf_pasv_ptc_nom_pl, nil, nil, nil, "[[essēmus]]", "[[essētis]]", "[[essent]]")
end
end
end
end
local function make_perf_and_supine(data, typeinfo)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
end
local function make_sigm(data, typeinfo, sigm_stem)
local subtypes = typeinfo.subtypes
if not subtypes.sigm then
return
end
local forms = data.forms
if type(sigm_stem) ~= "table" then
sigm_stem = {sigm_stem}
end
local noteindex = table_len(data.footnotes) + 1
-- Deponent verbs use the passive form
for _, stem in ipairs(sigm_stem) do
-- Sigmatic future active indicative
add_forms(forms, "sigf_actv_indc", stem, "ō", "is", "it", "imus", "itis", "int")
-- Sigmatic future passive indicative
if subtypes.sigmpasv then
add_forms(forms, "sigf_pasv_indc", stem, "or", "eris", "itur", nil, nil, nil) -- Plurals not attested.
end
-- Sigmatic future active subjunctive
add_forms(forms, "siga_actv_subj", stem, "im", "īs", "īt", "īmus", "ītis", "int")
-- Perfect infinitive
if not no_inf then
add_form(forms, "sigm_actv_inf", stem, "ere")
end
end
data.form_footnote_indices["sigm"] = noteindex
if subtypes.depon then
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|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 (which is not attested in the plural for any verb).'
else
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|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 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\"), which is not attested in the plural for any verb.'
end
end
end
make_conjugation["1st"] = function(args, data, typeinfo)
insert_if_not(data.title, "[[Appendix:Latin first conjugation|first conjugation]]")
set_conj_categories("first", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres("1st", data, typeinfo, pres_stem)
make_perf_and_supine(data, typeinfo)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
local forms = data.forms
if pres_stem == "dīlapid" then
add_form(forms, "3p_sigf_actv_indc", "", "dīlapidāssunt", 2)
elseif pres_stem == "invol" then
add_form(forms, "3s_sigf_actv_indc", "", "involāsit", 2)
elseif pres_stem == "viol" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_futp_actv_indc", "", "violārint", 2)
add_form(forms, "3p_perf_actv_subj", "", "violārint", 2)
add_form(forms, "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] = "Old Latin."
end
end
make_conjugation["2nd"] = function(args, data, typeinfo)
insert_if_not(data.title, "[[Appendix:Latin second conjugation|second conjugation]]")
set_conj_categories("second", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres("2nd", data, typeinfo, pres_stem)
make_perf_and_supine(data, typeinfo)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if pres_stem == "noc" then
add_form(data.forms, "3s_siga_actv_subj", "", "noxsīt", 2)
end
end
make_conjugation["3rd"] = function(args, data, typeinfo)
insert_if_not(data.title, "[[Appendix:Latin third conjugation|third conjugation]]")
set_conj_categories("third", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres("3rd", data, typeinfo, pres_stem)
make_perf_and_supine(data, typeinfo)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if not pres_stem then
return
elseif toNFD(pres_stem):match("[aeiouyAEIOUY]" .. MACRON .. "sc$") then
insert_if_not(data.categories, "Latin inchoative verbs")
end
if pres_stem:match("nōsc$") then
typeinfo.subtypes.poetsyncperf = true
elseif pres_stem == "ulcīsc" then
local forms = data.forms
local formval = forms["1s_sigf_actv_indc"]
if type(formval) ~= "table" then
formval = {formval}
end
forms["1s_sigf_actv_indc"] = formval
local noteindex = table_len(data.footnotes) + 1
for i, form in ipairs(formval) do
if form == "ulsō" then
add_form(forms, "1s_sigf_actv_indc", "ull", "ō", i + 1)
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ō\".'
break
end
end
end
end
make_conjugation["3rd-io"] = function(args, data, typeinfo)
insert_if_not(data.title, "[[Appendix:Latin third conjugation|third conjugation]] ''iō''-variant")
set_conj_categories("third", 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
make_conjugation["4th"] = function(args, data, typeinfo)
insert_if_not(data.title, "[[Appendix:Latin fourth conjugation|fourth conjugation]]")
set_conj_categories("fourth", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres("4th", data, typeinfo, pres_stem)
make_perf_and_supine(data, typeinfo)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
local forms = data.forms
if form_contains(forms["1s_pres_actv_indc"], "serviō") or form_contains(forms["1s_pres_actv_indc"], "saeviō") then
add_forms(forms, "impf_actv_indc", 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(forms, "futr_actv_indc", pres_stem,
{"iam", "ībō"},
{"iēs", "ībis"},
{"iet", "ībit"},
{"iēmus", "ībimus"},
{"iētis", "ībitis"},
{"ient", "ībunt"}
)
end
local subtypes = typeinfo.subtypes
if not (subtypes.alwayssyncperf or subtypes.optsyncperf) then
return
end
for key, formval in pairs(forms) do
if cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp") then
if type(formval) ~= "table" then
formval = {formval}
end
forms[key] = {}
for _, f in ipairs(formval) do
if subtypes.optsyncperf then
insert_if_not(forms[key], f)
end
insert_if_not(forms[key], ivi_ive(f))
end
end
end
end
-- Irregular conjugations.
local irreg_conjugations = {}
make_conjugation["irreg"] = function(args, data, typeinfo)
local verb = ine(args[1])
local prefix = ine(args[2])
if not verb then
if NAMESPACE ~= 10 then -- Template:
error("The verb to be conjugated has not been specified.")
end
verb = "sum"
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
for _, verb in ipairs{"aio", "aiio", "aijo", "ajo"} do
local stem = verb:sub(1, -2)
local i_stem = stem:gsub("j$", "i")
irreg_conjugations[verb] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]] iō-variant")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[active voice|active]]-only")
insert_if_not(title, "highly [[defective verb|defective]]")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin active-only verbs")
insert_if_not(categories, "Latin defective verbs")
-- Signal to {{la-verb}} to display the verb as irregular and highly defective
typeinfo.subtypes.irreg = true
typeinfo.subtypes.highlydef = true
local prefix = typeinfo.prefix or ""
forms["1s_pres_actv_indc"] = prefix .. stem .. "ō"
forms["2s_pres_actv_indc"] = prefix .. i_stem .. "s"
forms["3s_pres_actv_indc"] = prefix .. i_stem .. "t"
forms["3p_pres_actv_indc"] = prefix .. stem .. "unt"
forms["1s_impf_actv_indc"] = prefix .. stem .. "ēbam"
forms["2s_impf_actv_indc"] = prefix .. stem .. "ēbās"
forms["3s_impf_actv_indc"] = prefix .. stem .. "ēbat"
forms["1p_impf_actv_indc"] = prefix .. stem .. "ēbāmus"
forms["2p_impf_actv_indc"] = prefix .. stem .. "ēbātis"
forms["3p_impf_actv_indc"] = prefix .. stem .. "ēbant"
forms["2s_perf_actv_indc"] = prefix .. i_stem .. "stī"
forms["3s_perf_actv_indc"] = prefix .. i_stem .. "t"
forms["3p_perf_actv_indc"] = prefix .. stem .. "ērunt"
forms["2s_pres_actv_subj"] = prefix .. stem .. "ās"
forms["3s_pres_actv_subj"] = prefix .. stem .. "at"
forms["3p_pres_actv_subj"] = prefix .. stem .. "ant"
forms["2s_pres_actv_impr"] = prefix .. i_stem
forms["pres_actv_inf"] = prefix .. stem .. "ere"
forms["pres_actv_ptc"] = prefix .. stem .. "ēns"
end
end
irreg_conjugations["dico"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]]")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]] short [[imperative mood|imperative]]")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(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")
-- Old Latin regular imperative.
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "2s_pres_actv_impr", prefix, "dīc", 1)
data.form_footnote_indices["2s_pres_actv_impr"] = tostring(noteindex)
-- Old Latin future forms.
if prefix == "" then
add_form(forms, "1s_futr_actv_indc", "", "dīcēbō", 2)
add_form(forms, "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] = "Old Latin."
end
irreg_conjugations["do"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin first conjugation|first conjugation]]")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]] short ''a'' in most forms except " .. make_link(nil, "dās", "term") .. " and " .. make_link(nil, "dā", "term"))
insert_if_not(categories, "Latin first conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
-- Signal to {{la-verb}} 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(forms, "pres_actv_indc", prefix, "dō", "dās", "dat", "damus", "datis", "dant")
add_forms(forms, "impf_actv_indc", prefix, "dabam", "dabās", "dabat", "dabāmus", "dabātis", "dabant")
add_forms(forms, "futr_actv_indc", prefix, "dabō", "dabis", "dabit", "dabimus", "dabitis", "dabunt")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, "dor", {"daris", "dare"}, "datur", "damur", "daminī", "dantur")
add_forms(forms, "impf_pasv_indc", prefix, "dabar", {"dabāris", "dabāre"}, "dabātur", "dabāmur", "dabāminī", "dabantur")
add_forms(forms, "futr_pasv_indc", prefix, "dabor", {"daberis", "dabere"}, "dabitur", "dabimur", "dabiminī", "dabuntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "dem", "dēs", "det", "dēmus", "dētis", "dent")
add_forms(forms, "impf_actv_subj", prefix, "darem", "darēs", "daret", "darēmus", "darētis", "darent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", prefix, "der", {"dēris", "dēre"}, "dētur", "dēmur", "dēminī", "dentur")
add_forms(forms, "impf_pasv_subj", prefix, "darer", {"darēris", "darēre"}, "darētur", "darēmur", "darēminī", "darentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix, "dā", "date")
add_23_forms(forms, "futr_actv_impr", prefix, "datō", "datō", "datōte", "dantō")
add_2_forms(forms, "pres_pasv_impr", prefix, "dare", "daminī")
-- no 2p form
add_23_forms(forms, "futr_pasv_impr", prefix, "dator", "dator", nil, "dantor")
-- Present infinitives
forms["pres_actv_inf"] = prefix .. "dare"
forms["pres_pasv_inf"] = prefix .. "darī"
-- Imperfective participles
forms["pres_actv_ptc"] = prefix .. "dāns"
-- Gerund
make_gerund(data, typeinfo, prefix .. "dand")
end
irreg_conjugations["duco"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]]")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]] short [[imperative mood|imperative]]")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(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(forms, "2s_pres_actv_impr", prefix, "dūc", 1)
end
irreg_conjugations["edo"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]]")
insert_if_not(title, "some [[Appendix:Latin irregular verbs|irregular]] alternative forms")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
-- Signal to {{la-verb}} 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(forms, "pres_actv_indc", prefix, nil, "ēs", "ēst", nil, "ēstis", nil)
-- Passive imperfective indicative
add_form(forms, "3s_pres_pasv_indc", prefix, "ēstur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "edim", "edīs", "edit", "edīmus", "edītis", "edint")
add_forms(forms, "impf_actv_subj", prefix, "ēssem", "ēssēs", "ēsset", "ēssēmus", "ēssētis", "ēssent")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ēs", "ēste")
add_23_forms(forms, "futr_actv_impr", prefix, "ēstō", "ēstō", "ēstōte", nil)
-- Present infinitives
add_form(forms, "pres_actv_inf", prefix, "ēsse")
end
irreg_conjugations["eo"] = function(args, data, typeinfo)
local forms = data.forms
insert_if_not(data.title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(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(forms, "pres_actv_indc", prefix, "eō", "īs", "it", "īmus", "ītis",
prefix == "prōd" and {"eunt", "īnunt"} or "eunt")
add_forms(forms, "impf_actv_indc", prefix, "ībam", "ībās", "ībat", "ībāmus", "ībātis", "ībant")
add_forms(forms, "futr_actv_indc", prefix, "ībō", "ībis", "ībit", "ībimus", "ībitis", "ībunt")
-- Active perfective indicative
add_form(forms, "1s_perf_actv_indc", prefix, "īvī")
forms["2s_perf_actv_indc"] = {prefix .. "īstī", prefix .. "īvistī"}
add_form(forms, "3s_perf_actv_indc", prefix, "īvit")
forms["2p_perf_actv_indc"] = prefix .. "īstis"
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, "eor", { "īris", "īre"}, "ītur", "īmur", "īminī", "euntur")
add_forms(forms, "impf_pasv_indc", prefix, "ībar", {"ībāris", "ībāre"}, "ībātur", "ībāmur", "ībāminī", "ībantur")
add_forms(forms, "futr_pasv_indc", prefix, "ībor", {"īberis", "ībere"}, "ībitur", "ībimur", "ībiminī", "ībuntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", prefix, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Active perfective subjunctive
forms["1s_plup_actv_subj"] = prefix .. "īssem"
forms["2s_plup_actv_subj"] = prefix .. "īssēs"
forms["3s_plup_actv_subj"] = prefix .. "īsset"
forms["1p_plup_actv_subj"] = prefix .. "īssēmus"
forms["2p_plup_actv_subj"] = prefix .. "īssētis"
forms["3p_plup_actv_subj"] = prefix .. "īssent"
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", prefix, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "impf_pasv_subj", prefix, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", prefix, "ītō", "ītō", "ītōte", "euntō")
add_2_forms(forms, "pres_pasv_impr", prefix, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", prefix, "ītor", "ītor", nil, "euntor")
-- Present infinitives
forms["pres_actv_inf"] = prefix .. "īre"
forms["pres_pasv_inf"] = prefix .. "īrī"
-- Perfect/future infinitives
forms["perf_actv_inf"] = prefix .. "īsse"
-- Imperfective participles
forms["pres_actv_ptc"] = prefix .. "iēns"
-- Gerund
make_gerund(data, typeinfo, prefix .. "eund")
end
local function fio(forms, prefix, voice)
-- Active/passive imperfective indicative
add_forms(forms, "pres_" .. voice .. "_indc", prefix,
"fīō", "fīs", "fit", "fīmus", "fītis", "fīunt")
add_forms(forms, "impf_" .. voice .. "_indc", prefix .. "fīēb",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_" .. voice .. "_indc", prefix .. "fī",
"am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperfective subjunctive
add_forms(forms, "pres_" .. voice .. "_subj", prefix .. "fī",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_" .. voice .. "_subj", prefix .. "fier",
"em", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperative
add_2_forms(forms, "pres_" .. voice .. "_impr", prefix .. "fī", "", "te")
add_23_forms(forms, "futr_" .. voice .. "_impr", prefix .. "fī", "tō", "tō", "tōte", "untō")
-- Active/passive present infinitive
add_form(forms, "pres_" .. voice .. "_inf", prefix, "fierī")
end
irreg_conjugations["facio"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]] ''iō''-variant")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]] and partially [[suppletive]] in the [[passive voice|passive]]")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
local prefix = typeinfo.prefix or ""
make_pres("3rd-io", data, typeinfo, prefix .. "fac", "nopass")
make_gerund(data, typeinfo, prefix .. "faciend", "und-variant")
make_perf(data, prefix .. "fēc")
make_supine(data, typeinfo, prefix .. "fact")
make_sigm(data, typeinfo, prefix .. "fax")
if prefix == "" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3s_perf_actv_indc", "", "fēced")
data.form_footnote_indices["3s_perf_actv_indc"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
-- Active imperative
add_form(forms, "2s_pres_actv_impr", "", "fac", 1)
-- Sigmatic forms
add_form(forms, "1s_sigf_actv_indc", "", {"faxsō", "facsō", "faxiō"})
add_form(forms, "2s_sigf_actv_indc", "", {"faxsis", "facsis", "facxis", "facxsis"})
add_form(forms, "3s_sigf_actv_indc", "", "faxsit")
add_form(forms, "1p_sigf_actv_indc", "", "faxsimus")
add_form(forms, "2p_sigf_actv_indc", "", "faxsitis")
add_form(forms, "3p_sigf_actv_indc", "", "faxsint")
add_form(forms, "1s_siga_actv_subj", "", {"faxsim", "faxēm"})
add_form(forms, "2s_siga_actv_subj", "", {"faxsīs", "faxseis", "faxeis", "faxēs"})
add_form(forms, "3s_siga_actv_subj", "", {"faxsīt", "faxeit", "faxēt"})
add_form(forms, "1p_siga_actv_subj", "", {"faxsīmus", "faxeimus"})
add_form(forms, "2p_siga_actv_subj", "", {"faxsītis", "faxeitis"})
add_form(forms, "3p_siga_actv_subj", "", {"faxsint", "faxēnt"})
end
fio(forms, prefix, "pasv")
end
irreg_conjugations["fio"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]] ''iō''-variant")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]] long ''ī''")
if not typeinfo.subtypes.nosup then
insert_if_not(title, "[[suppletive]] in the [[supine tense|supine]] stem")
end
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
typeinfo.subtypes.semidepon = true
typeinfo.subtypes.nosupfutractv = true
local prefix = typeinfo.prefix or ""
fio(forms, prefix, "actv")
make_supine(data, typeinfo, prefix .. "fact")
forms["futr_actv_inf"] = forms["futr_pasv_inf"]
-- Imperfective participles
forms["pres_actv_ptc"] = nil
-- Gerund
make_gerund(data, typeinfo, prefix .. "fiend", "und-variant")
end
irreg_conjugations["fero"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin third conjugation|third conjugation]]")
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]]")
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
-- Signal to {{la-verb}} 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"})
else
make_perf(data, prefix_perf .. "tul")
end
make_supine(data, typeinfo, prefix_supine .. "lāt")
-- Active imperfective indicative
forms["2s_pres_actv_indc"] = prefix_pres .. "fers"
forms["3s_pres_actv_indc"] = prefix_pres .. "fert"
forms["2p_pres_actv_indc"] = prefix_pres .. "fertis"
-- Passive imperfective indicative
forms["3s_pres_pasv_indc"] = prefix_pres .. "fertur"
-- Active imperfective subjunctive
forms["1s_impf_actv_subj"] = prefix_pres .. "ferrem"
forms["2s_impf_actv_subj"] = prefix_pres .. "ferrēs"
forms["3s_impf_actv_subj"] = prefix_pres .. "ferret"
forms["1p_impf_actv_subj"] = prefix_pres .. "ferrēmus"
forms["2p_impf_actv_subj"] = prefix_pres .. "ferrētis"
forms["3p_impf_actv_subj"] = prefix_pres .. "ferrent"
-- Passive present indicative
forms["2s_pres_pasv_indc"] = {prefix_pres .. "ferris", prefix_pres .. "ferre"}
-- Passive imperfective subjunctive
forms["1s_impf_pasv_subj"] = prefix_pres .. "ferrer"
forms["2s_impf_pasv_subj"] = {prefix_pres .. "ferrēris", prefix_pres .. "ferrēre"}
forms["3s_impf_pasv_subj"] = prefix_pres .. "ferrētur"
forms["1p_impf_pasv_subj"] = prefix_pres .. "ferrēmur"
forms["2p_impf_pasv_subj"] = prefix_pres .. "ferrēminī"
forms["3p_impf_pasv_subj"] = prefix_pres .. "ferrentur"
-- Imperative
forms["2s_pres_actv_impr"] = prefix_pres .. "fer"
forms["2p_pres_actv_impr"] = prefix_pres .. "ferte"
forms["2s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["3s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["2p_futr_actv_impr"] = prefix_pres .. "fertōte"
forms["2s_pres_pasv_impr"] = prefix_pres .. "ferre"
forms["2s_futr_pasv_impr"] = prefix_pres .. "fertor"
forms["3s_futr_pasv_impr"] = prefix_pres .. "fertor"
-- Present infinitives
forms["pres_actv_inf"] = prefix_pres .. "ferre"
forms["pres_pasv_inf"] = prefix_pres .. "ferrī"
if prefix_perf == "" then
local noteindex = table_len(data.footnotes) + 1
for slot, form in pairs(forms) do
if type(form) == "table" then
for _, f in ipairs(form) do
if f:match("^tetul") then
data.form_footnote_indices[slot] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
break
end
end
end
end
end
end
irreg_conjugations["inquam"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "highly [[defective verb|defective]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin defective verbs")
-- Signal to {{la-verb}} to display the verb as highly defective
-- (it already displays as irregular because conj == "irreg" and
-- subconj == "irreg")
typeinfo.subtypes.highlydef = true
forms["1s_pres_actv_indc"] = "inquam"
forms["2s_pres_actv_indc"] = "inquis"
forms["3s_pres_actv_indc"] = "inquit"
forms["1p_pres_actv_indc"] = "inquimus"
forms["2p_pres_actv_indc"] = "inquitis"
forms["3p_pres_actv_indc"] = "inquiunt"
forms["2s_futr_actv_indc"] = "inquiēs"
forms["3s_futr_actv_indc"] = "inquiet"
forms["3s_impf_actv_indc"] = "inquiēbat"
forms["1s_perf_actv_indc"] = "inquiī"
forms["2s_perf_actv_indc"] = "inquistī"
forms["3s_perf_actv_indc"] = "inquit"
forms["3s_pres_actv_subj"] = "inquiat"
forms["2s_pres_actv_impr"] = "inque"
forms["2s_futr_actv_impr"] = "inquitō"
forms["3s_futr_actv_impr"] = "inquitō"
forms["pres_actv_ptc"] = "inquiēns"
end
-- Handle most forms of volō, mālō, nōlō.
local function volo_malo_nolo(data, indc_stem, subj_stem)
local forms = data.forms
-- Present active indicative needs to be done individually as each
-- verb is different.
add_forms(forms, "impf_actv_indc", indc_stem .. "ēb", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", indc_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", subj_stem, "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", subj_stem .. "l", "em", "ēs", "et", "ēmus", "ētis", "ent")
-- Present infinitives
forms["pres_actv_inf"] = subj_stem .. "le"
-- Imperfective participles
forms["pres_actv_ptc"] = indc_stem .. "ēns"
end
irreg_conjugations["volo"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]] in the [[second-person]] [[singular]] [[indicative mood|indicative]] [[present tense|present]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
local prefix = typeinfo.prefix or ""
typeinfo.subtypes.nopass = true
typeinfo.subtypes.noimp = true
typeinfo.subtypes.supfutractvonly = true
make_perf(data, prefix .. "volu")
make_supine(data, typeinfo, prefix .. "volit")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, "volō", "vīs", "vult", "volumus", "vultis", "volunt")
volo_malo_nolo(data, prefix .. "vol", prefix .. "vel")
-- Additional Old Latin forms.
if prefix == "" then
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", prefix, nil, nil, "volt", nil, "voltis", nil)
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
-- vol- in the present subjunctive.
add_forms(forms, "pres_actv_subj", prefix .. "vol", "im", "īs", "it", "īmus", "ītis", "int")
for slot in pairs(data.forms) do
if cfind(slot, "pres_actv_subj") then
data.form_footnote_indices[slot] = noteindex
end
end
end
end
irreg_conjugations["malo"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]] in the [[second-person]] [[singular]] [[indicative mood|indicative]] [[present tense|present]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
typeinfo.subtypes.nopass = true
typeinfo.subtypes.noimp = true
make_perf(data, "mālu")
-- Active imperfective indicative
add_forms(forms, "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)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "[[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]] in the [[second-person]] [[singular]] [[indicative mood|indicative]] [[present tense|present]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
typeinfo.subtypes.nopass = true
make_perf(data, "nōlu")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", "", "nōlō", "nōn vīs", "nōn vult", "nōlumus", "nōn vultis", "nōlunt")
add_forms(forms, "impf_actv_indc", "nōlēb", "am", "ās", "at", "āmus", "ātis", "ant")
volo_malo_nolo(data, "nōl", "nōl")
-- Imperative
add_2_forms(forms, "pres_actv_impr", "nōlī", "", "te")
add_23_forms(forms, "futr_actv_impr", "nōl", "itō", "itō", "itōte", "untō")
-- Additional Old Latin forms.
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", "", nil, "nēvīs", {"nōn volt", "nēvolt"}, nil, {"nōn voltis", "nōltis"}, nil)
data.form_footnote_indices["2s_pres_actv_indc"] = noteindex
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
end
irreg_conjugations["possum"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "highly [[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
typeinfo.subtypes.passimpers = true
typeinfo.subtypes.passimpersold = true
make_perf(data, "potu")
-- Active imperfective indicative, impersonal passive
add_forms(forms, "pres_actv_indc", "", "possum", "potes", "potest", "possumus", "potestis", "possunt")
add_forms(forms, "impf_actv_indc", "poter", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", "poter", "ō", {"is", "e"}, "it", "imus", "itis", "unt")
forms["3s_pres_pasv_indc"] = "potestur"
forms["3s_impf_pasv_indc"] = "poterātur"
forms["3s_futr_pasv_indc"] = "poteritur"
-- Active imperfective subjunctive, impersonal passive
add_forms(forms, "pres_actv_subj", "poss", "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", "poss", "em", "ēs", "et", "ēmus", "ētis", "ent")
forms["3s_pres_pasv_subj"] = "possītur"
forms["3s_impf_pasv_subj"] = "possētur"
-- Present infinitives
forms["pres_actv_inf"] = {"posse", "potesse"}
-- Imperfective participles
forms["pres_actv_ptc"] = "potēns"
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin. The passive forms are only used to govern a passive infinitive; e.g. " .. mw.getCurrentFrame():preprocess("{{uxi|la|nec retrahi '''potestur''' imperiis|t=\"nor '''can it''' be withdrawn by commands\"}}") .. "."
noteindex = tostring(noteindex)
for slot in pairs(data.forms) do
if cfind(slot, "pasv") then
data.form_footnote_indices[slot] = noteindex
end
end
data.form_footnote_indices["pres_actv_inf"] = noteindex
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 (ugsub(prefix, "([aeiouyAEIOUY])" .. length_mark .. "n$", "%1" .. MACRON .. "n"))
end
irreg_conjugations["sum"] = function(args, data, typeinfo)
local title, categories, forms = data.title, data.categories, data.forms
insert_if_not(title, "highly [[Appendix:Latin irregular verbs|irregular]]")
insert_if_not(title, "[[suppletive]]")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(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
add_forms(forms, "pres_actv_indc", prefix_s, "sum", nil, nil, "sumus", nil, "sunt")
add_forms(forms, "pres_actv_indc", prefix_e, nil, "es", "est", nil, "estis", nil)
add_forms(forms, "impf_actv_indc", prefix_e, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futr_actv_indc", prefix_e, "erō", {"eris", "ere"}, "erit", "erimus", "eritis", "erunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix_s, "sim", "sīs", "sit", "sīmus", "sītis", "sint")
add_forms(forms, "pres_actv_subj", prefix_f, "fuam", "fuās", "fuat", "fuāmus", "fuātis", "fuant")
if prefix_s == "ad" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_pres_actv_subj", "", "adessint", 2)
data.form_footnote_indices["3p_pres_actv_subj"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
end
add_forms(forms, "impf_actv_subj", prefix_e, "essem", "essēs", "esset", "essēmus", "essētis", "essent")
add_forms(forms, "impf_actv_subj", prefix_f, "forem", "forēs", "foret", "forēmus", "forētis", "forent")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix_e, "es", "este")
add_23_forms(forms, "futr_actv_impr", prefix_e, "estō", "estō", "estōte", nil)
add_form(forms, "3p_futr_actv_impr", prefix_s, "suntō")
-- Infinitives
forms["pres_actv_inf"] = prefix_e .. "esse"
forms["futr_actv_inf"] = {"[[" .. prefix_f .. "futūrum]] [[esse]]", prefix_f .. "fore"}
forms["perp_actv_inf"] = "[[" .. prefix_f .. "futūrum]] [[fuisse]]"
-- Imperfective participles
if prefix == "ab" or prefix == "con" or prefix == "prae" then
forms["pres_actv_ptc"] = prefix_s .. "sēns"
end
end
local conjugations_mt = {}
function conjugations_mt:__call(conj, args, data, typeinfo)
if conj ~= "irreg" then
get_regular_stems(args, typeinfo)
end
return self[conj](args, data, typeinfo)
end
setmetatable(make_conjugation, conjugations_mt)
-- 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 "—".
local function show_form(formval, accel)
if not formval then
return "—"
elseif type(formval) ~= "table" then
formval = {formval}
elseif table_len(formval) == 0 then
return "—"
end
for slot, form in ipairs(formval) do
if form_is_empty(form) then
formval[slot] = "—"
elseif form:match("[[%]]") 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.
formval[slot] = make_link(form)
else
formval[slot] = make_link(form, nil, nil, accel)
end
end
return concat(formval, ",<br> ")
end
local 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'] = {'futp'},
['perp'] = {'perf', 'potn'},
['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, forms = data.actual_lemma[1], data.forms
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
insert(tags, tag)
end
end
-- put the case first for verbal nouns
local accel = {form = concat(tags, "|"), lemma = accel_lemma}
forms[slot] = show_form(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
insert(valid_forms, subform)
end
end
end
return valid_forms
end
function export.get_lemma_forms(data, do_linked)
local linked_prefix, forms = do_linked and "linked_" or "", data.forms
for _, slot in ipairs(potential_lemma_slots) do
local lemma_forms = export.get_valid_forms(forms[linked_prefix .. slot])
if table_len(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 "—"
end
local lemma_links = {}
for _, subform in ipairs(lemma_forms) do
insert(lemma_links, make_link(nil, subform, "term"))
end
return concat(lemma_links, ", ")
end
local tenses = {
["pres"] = "present",
["impf"] = "imperfect",
["futr"] = "future",
["perf"] = "perfect",
["plup"] = "pluperfect",
["futp"] = "future perfect",
["perp"] = "perfect potential",
["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",
}
--]]
local function make_row(data, prefixes, headspan, cellspan, rowslot, rowname, class, fn)
local row = {}
if rowname then
insert(row, ('\n! class="%s"%s | %s%s'):format(class, headspan == 1 and "" or (' colspan="%d"'):format(headspan), rowname, fn or ""))
end
local has_row, forms = false, data.forms
if not form_is_empty(forms[rowslot]) then
if type(forms[rowslot]) == "table" then
if table_len(forms[rowslot]) > 1 then
error("Row slot " .. rowslot .. " cannot have more than one value.")
end
forms[rowslot] = forms[rowslot][1]
end
insert(row, '\n! colspan="12" class="roa-compound-row" |' .. forms[rowslot])
has_row = true
else
for _, prefix in ipairs(prefixes) do
local slot = prefix .. (rowslot and "_" .. rowslot or "")
insert(row, ('\n| colspan="%d" | '):format(cellspan) .. forms[slot] .. (
data.form_footnote_indices[slot] == nil and "" or
'<sup class="roa-red-superscript">' .. data.form_footnote_indices[slot] .. "</sup>"
))
if not form_is_empty(forms[slot]) then
has_row = true
end
end
end
return has_row and concat(row) or false
end
local function make_group(data, _tenses, voice, mood, class)
local group, persons = {}, {"1s", "2s", "3s", "1p", "2p", "3p"}
for _, tense in ipairs(_tenses) do
local fn = ""
if tense == "sigf" or tense == "siga" then
fn = data.form_footnote_indices["sigm"]
fn = fn and ('<sup class="roa-red-superscript">' .. fn .. "</sup>") or ""
end
local row = make_row(data, persons, 1, 2, tense .. "_" .. voice .. "_" .. mood, tenses[tense], class, fn)
if row then
insert(group, row)
end
end
return #group > 0 and ('\n|-\n! rowspan="' .. tostring(#group) .. '" class="' .. class .. '" | ' .. voices[voice] .. concat(group, "\n|-")) or false
end
local function make_section(data, mood, _tenses)
local section, name = {}, moods[mood]
local class = "roa-" .. name .. "-left-rail"
for _, voice in ipairs{"actv", "pasv"} do
local group = make_group(data, _tenses, voice, mood, class)
if group then
insert(section, group)
end
end
if #section == 0 then
return ""
end
return (([=[
|-
! colspan="2" rowspan="2" class="%CLASS" | %NAME
! colspan="6" class="%CLASS" | ''singular''
! colspan="6" class="%CLASS" | ''plural''
|-
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]]=]):gsub("%%%u+", function(m)
return m == "%NAME" and name or m == "%CLASS" and class or m
end)) .. concat(section)
end
local function make_indc_rows(data)
return make_section(data, "indc", {"pres", "impf", "futr", "perf", "plup", "futp", "sigf"})
end
local function make_subj_rows(data)
return make_section(data, "subj", {"pres", "impf", "perf", "plup", "siga"})
end
local function make_impr_rows(data)
return make_section(data, "impr", {"pres", "futr"})
end
local function get_nonfin_cells(t)
local cells = {}
for _, f in ipairs{"inf", "ptc"} do
for _, v in ipairs{"actv", "pasv"} do
insert(cells, t .. "_" .. v .. "_" .. f)
end
end
return cells
end
local function make_nonfin_rows(data)
local nonfin = {}
for _, t in ipairs{"pres", "futr", "perf", "futp", "perp"} do
local row = make_row(data, get_nonfin_cells(t), 2, 3, nil, tenses[t], "roa-nonfinite-header")
if row then
insert(nonfin, row)
end
end
if #nonfin == 0 then
return ""
end
return [=[
|-
! colspan="2" rowspan="2" class="roa-nonfinite-header" | non-finite forms
! colspan="6" class="roa-nonfinite-header" | infinitive
! colspan="6" class="roa-nonfinite-header" | participle
|-
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
|-]=] .. concat(nonfin, "\n|-")
end
local function make_vn_rows(data)
local vn = make_row(data, {"gen_ger", "dat_ger", "acc_ger", "abl_ger", "acc_sup", "abl_sup"}, nil, 2, nil, nil, "roa-nonfinite-header")
if not vn then
return ""
end
return [=[
|-
! colspan="2" rowspan="3" class="roa-nonfinite-header" | verbal nouns
! colspan="8" class="roa-nonfinite-header" | gerund
! colspan="4" class="roa-nonfinite-header" | supine
|-
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | genitive
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | dative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
|-]=] .. vn
end
local function make_footnotes(data)
local tbl, i = {}, 0
for k, v in pairs(data.footnotes) do
i = i + 1
tbl[i] = '<sup class="roa-red-superscript">' .. tostring(k) .. '</sup>' .. v .. '<br>'
end
return concat(tbl)
end
-- Make the table
local function make_table(data)
data.actual_lemma = export.get_lemma_forms(data)
convert_forms_into_links(data)
local title = data.title
return require("Module:TemplateStyles")("Module:roa-verb/style.css") .. [=[
<div class="NavFrame">
<div class="NavHead"> Conjugation of ]=] .. get_displayable_lemma(data.actual_lemma) .. (table_len(title) > 0 and " (" .. concat(title, ", ") .. ")" or "") .. [=[</div>
<div class="NavContent">
{| class="roa-inflection-table" data-toggle-category="inflection"
]=] .. make_indc_rows(data) .. make_subj_rows(data) .. make_impr_rows(data) .. make_nonfin_rows(data) .. make_vn_rows(data) .. [=[
|}</div></div>]=].. make_footnotes(data)
end
local function checkexist(data)
if NAMESPACE ~= 0 then
return
end
local outerbreak = false
local categories = data.categories
for _, conjugation in pairs(data.forms) do
if conjugation then
if type(conjugation) ~= "table" 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
insert_if_not(categories, "Latin verbs with red links in their inflection tables")
outerbreak = true
break
end
end
end
end
if outerbreak then
break
end
end
end
-- functions for creating external search hyperlinks
local function cleanup(x)
x:gsub("[[%]]", "")
:gsub(" ", "+")
return toNFC(ugsub(toNFD(x), "[^%w]+", ""))
end
local function flatten_values(t)
t = flatten(t)
local i = 1
while true do
local v = t[i]
if v == nil then
return t
elseif cfind(v, "<") then
remove(t, i)
else
t[i] = cleanup(v)
i = i + 1
end
end
end
local function link_google_books(verb, forms, domain)
local 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
local function forms_N_to_link(fs, N, args, site)
return '[https://www.google.com/search?'..args..'&q='..site..'+%22'.. concat(fs, "%22+OR+%22") ..'%22 '..N..']'
end
local 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 concat(links, ' - ')
end
return "Google "..domain.." forms of "..verb.." : "..make_links_txt(forms, 30, domain)
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 = 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)
end
local verb = data['forms']['1s_pres_actv_indc'] ~= nil and ('[[' .. toNFC(ugsub(toNFD(data['forms']['1s_pres_actv_indc']), '[^%w]+', "")) .. '|' .. data['forms']['1s_pres_actv_indc'] .. ']]') or 'verb'
return link_google_books(verb, flatten_values(data['forms']), domain)
end
return export