// morphology-peo.el - Old Persian morphology for the NLG engine. // // Implements Old Persian verb conjugation and noun declension for the ca. 600-300 BCE // period (Achaemenid Empire). Designed as a companion to morphology.el and called // by the engine when the language profile code is "peo". // // Language profile: code=peo, name=Old Persian, morph_type=fusional, word_order=SOV, // question_strategy=particle, script=latin, family=iranian. // // Old Persian is attested primarily in royal cuneiform inscriptions (Behistun, // Persepolis, Naqsh-e Rostam, etc.). The transliteration used here follows the // standard scholarly convention with macrons for long vowels (ā, ī, ū). The corpus // is small — most productive forms are individually attested in the inscriptions. // // Verb conjugation covered: // Tenses: present, past (imperfect) // Persons: first/second/third x singular/plural (slots 0-5) // Irregulars: ah- (to be), kar- (to do/make), xšāya- (to rule), // tar- (to cross/overcome), dā- (to give) // Canonical map: "be" -> "ah-" // Pro-drop: the subject pronoun is typically omitted; the engine provides // conjugated forms only and does not add pronouns. // // Noun declension covered: // a-stem masculine (like "dahyu" — country/land) // Cases: nominative, accusative, genitive, dative x singular, plural // (Many case distinctions collapsed in practice; 4 cases implemented) // Articles: none — Old Persian has no article system // // Depends on: morphology.el (str_eq, str_len, str_slice, str_ends_with) // ── String helpers ───────────────────────────────────────────────────────────── import "morphology.el" fn peo_drop(s: String, n: Int) -> String { let len: Int = str_len(s) if n >= len { return "" } return str_slice(s, 0, len - n) } fn peo_ends(s: String, suf: String) -> Bool { return str_ends_with(s, suf) } // ── Person/number slot ───────────────────────────────────────────────────────── // // Maps person x number to a 0-based paradigm slot. // 0 = 1st singular (adam) // 1 = 2nd singular (tuvam) // 2 = 3rd singular (hauv) // 3 = 1st plural (vayam) // 4 = 2nd plural (yuvam) // 5 = 3rd plural (taiy) fn peo_slot(person: String, number: String) -> Int { if str_eq(person, "first") { if str_eq(number, "singular") { return 0 } return 3 } if str_eq(person, "second") { if str_eq(number, "singular") { return 1 } return 4 } // third if str_eq(number, "singular") { return 2 } return 5 } // ── Regular present endings ──────────────────────────────────────────────────── // // Old Persian present active indicative endings (Schmitt 1991 reconstruction): // Sg: 1st -āmiy 2nd -ahiy 3rd -atiy // Pl: 1st -āmahy 2nd -ātā 3rd -antiy // // These attach to the present stem. The present stem typically equals the // verbal root (sometimes with a thematic vowel -a-). fn peo_present_suffix(slot: Int) -> String { if slot == 0 { return "āmiy" } if slot == 1 { return "ahiy" } if slot == 2 { return "atiy" } if slot == 3 { return "āmahy" } if slot == 4 { return "ātā" } return "antiy" } // ── Regular past (imperfect) endings ────────────────────────────────────────── // // Old Persian imperfect (past) endings. The imperfect is formed with the augment // a- prefixed to the stem, but since many verbs in the inscriptions appear without // the augment or with it fossilised, the engine omits the augment prefix and // returns only the stem + ending combination. // // Imperfect endings: // Sg: 1st -am 2nd -ā 3rd -a // Pl: 1st -āmā 2nd -ātā 3rd -ā fn peo_past_suffix(slot: Int) -> String { if slot == 0 { return "am" } if slot == 1 { return "ā" } if slot == 2 { return "a" } if slot == 3 { return "āmā" } if slot == 4 { return "ātā" } return "ā" } // ── Irregular verb tables ────────────────────────────────────────────────────── // ah- (to be) — the Old Persian verb for being/existence // Present: amiy, ahiy, astiy, amahy, astā, hatiy // Past: āham, āha, āha, āhama, āhata, āhan fn peo_ah_present(slot: Int) -> String { if slot == 0 { return "amiy" } if slot == 1 { return "ahiy" } if slot == 2 { return "astiy" } if slot == 3 { return "amahy" } if slot == 4 { return "astā" } return "hatiy" } fn peo_ah_past(slot: Int) -> String { if slot == 0 { return "āham" } if slot == 1 { return "āha" } if slot == 2 { return "āha" } if slot == 3 { return "āhama" } if slot == 4 { return "āhata" } return "āhan" } // kar- (to do/make) — highly productive verb, uses present stem kun-/kunav- // Present: kunāmiy, kunāhiy, kunautiy, kunāmahy, kunātā, kunavantiy // Past: akunavam (1sg), akunava (3sg) — limited attestation; simplified fn peo_kar_present(slot: Int) -> String { if slot == 0 { return "kunāmiy" } if slot == 1 { return "kunāhiy" } if slot == 2 { return "kunautiy" } if slot == 3 { return "kunāmahy" } if slot == 4 { return "kunātā" } return "kunavantiy" } fn peo_kar_past(slot: Int) -> String { if slot == 0 { return "akunavam" } if slot == 1 { return "akunavā" } if slot == 2 { return "akunava" } if slot == 3 { return "akunavāmā" } if slot == 4 { return "akunavātā" } return "akunavan" } // xšāya- (to rule) — verb of the royal inscriptions, thematic stem xšāya- // Present: xšāyāmiy, xšāyāhiy, xšāyatiy, xšāyāmahy, xšāyātā, xšāyantiy fn peo_xsaya_present(slot: Int) -> String { if slot == 0 { return "xšāyāmiy" } if slot == 1 { return "xšāyāhiy" } if slot == 2 { return "xšāyatiy" } if slot == 3 { return "xšāyāmahy" } if slot == 4 { return "xšāyātā" } return "xšāyantiy" } // tar- (to cross/overcome) — limited attestation in inscriptions // Attested: taratiy (3sg pres), tarantiy (3pl pres) // Other slots approximated using regular present endings on stem tar- fn peo_tar_present(slot: Int) -> String { if slot == 2 { return "taratiy" } if slot == 5 { return "tarantiy" } // Other slots: apply regular endings to stem tar- return "tar" + peo_present_suffix(slot) } // dā- (to give) — long-vowel root, contracts in some forms // Present: dāmiy, dāhiy, dātiy, dāmahy, dātā, dantiy fn peo_da_present(slot: Int) -> String { if slot == 0 { return "dāmiy" } if slot == 1 { return "dāhiy" } if slot == 2 { return "dātiy" } if slot == 3 { return "dāmahy" } if slot == 4 { return "dātā" } return "dantiy" } fn peo_da_past(slot: Int) -> String { if slot == 0 { return "adām" } if slot == 1 { return "adāā" } if slot == 2 { return "adā" } if slot == 3 { return "adāmā" } if slot == 4 { return "adātā" } return "adān" } // ── Canonical verb mapping ───────────────────────────────────────────────────── // // Maps English semantic labels to Old Persian verbal stems / citation forms. fn peo_map_canonical(verb: String) -> String { if str_eq(verb, "be") { return "ah" } if str_eq(verb, "do") { return "kar" } if str_eq(verb, "make") { return "kar" } if str_eq(verb, "rule") { return "xšāya" } if str_eq(verb, "cross") { return "tar" } if str_eq(verb, "give") { return "dā" } return verb } // ── peo_conjugate: main conjugation entry point ─────────────────────────────── // // verb: Old Persian verbal stem or English canonical label // tense: "present" | "past" // person: "first" | "second" | "third" // number: "singular" | "plural" // // Returns the inflected form. Pro-drop language — the engine produces conjugated // verb forms only; subject pronouns are omitted unless explicitly generated by // the semantic layer. fn peo_conjugate(verb: String, tense: String, person: String, number: String) -> String { let v: String = peo_map_canonical(verb) let slot: Int = peo_slot(person, number) // ── ah- (to be) ─────────────────────────────────────────────────────────── if str_eq(v, "ah") { if str_eq(tense, "present") { return peo_ah_present(slot) } if str_eq(tense, "past") { return peo_ah_past(slot) } return v } // ── kar- (to do/make) ───────────────────────────────────────────────────── if str_eq(v, "kar") { if str_eq(tense, "present") { return peo_kar_present(slot) } if str_eq(tense, "past") { return peo_kar_past(slot) } return v } // ── xšāya- (to rule) ────────────────────────────────────────────────────── if str_eq(v, "xšāya") { if str_eq(tense, "present") { return peo_xsaya_present(slot) } // Past of xšāya-: apply imperfect endings to xšāya- stem if str_eq(tense, "past") { return "xšāya" + peo_past_suffix(slot) } return v } // ── tar- (to cross/overcome) ────────────────────────────────────────────── if str_eq(v, "tar") { if str_eq(tense, "present") { return peo_tar_present(slot) } if str_eq(tense, "past") { return "tar" + peo_past_suffix(slot) } return v } // ── dā- (to give) ───────────────────────────────────────────────────────── if str_eq(v, "dā") { if str_eq(tense, "present") { return peo_da_present(slot) } if str_eq(tense, "past") { return peo_da_past(slot) } return v } // ── Regular thematic verb ───────────────────────────────────────────────── // // Apply present or past endings directly to the stem. The stem is assumed // to be in the form supplied (Old Persian thematic stems typically end in -a-). if str_eq(tense, "present") { return v + peo_present_suffix(slot) } if str_eq(tense, "past") { return v + peo_past_suffix(slot) } // Unknown tense: return the bare stem return v } // ── a-stem masculine declension ("dahyu" — country/land) ───────────────────── // // The a-stem is the primary masculine nominal class in Old Persian. The paradigm // below uses "dahyu" (country, land — the most frequent noun in the inscriptions) // as the fully specified exemplar. // // Singular: nom dahyāuš acc dahyum gen dahyāuš dat dahyavā // Plural: nom dahyāva acc dahyūn gen dahyūnām dat dahyubiyā // // The singular nom/gen syncretism (both dahyāuš) is historically inherited from // Old Iranian; it is not a scribal error. fn peo_decline_astem(noun: String, gram_case: String, number: String) -> String { if str_eq(noun, "dahyu") { if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return "dahyāuš" } if str_eq(gram_case, "accusative") { return "dahyum" } if str_eq(gram_case, "genitive") { return "dahyāuš" } if str_eq(gram_case, "dative") { return "dahyavā" } return "dahyāuš" } if str_eq(gram_case, "nominative") { return "dahyāva" } if str_eq(gram_case, "accusative") { return "dahyūn" } if str_eq(gram_case, "genitive") { return "dahyūnām" } if str_eq(gram_case, "dative") { return "dahyubiyā" } return "dahyāva" } // Generic a-stem masculine: apply Old Persian nominal endings to base. // Base form assumed to be the uninflected stem (without final -u/-a). if str_eq(number, "singular") { if str_eq(gram_case, "nominative") { return noun + "āuš" } if str_eq(gram_case, "accusative") { return noun + "am" } if str_eq(gram_case, "genitive") { return noun + "āuš" } if str_eq(gram_case, "dative") { return noun + "avā" } return noun + "āuš" } // plural if str_eq(gram_case, "nominative") { return noun + "āva" } if str_eq(gram_case, "accusative") { return noun + "ūn" } if str_eq(gram_case, "genitive") { return noun + "ūnām" } if str_eq(gram_case, "dative") { return noun + "ubiyā" } return noun + "āva" } // ── peo_decline: main declension entry point ────────────────────────────────── // // noun: Old Persian noun (nominative singular or uninflected stem) // gram_case: "nominative" | "accusative" | "genitive" | "dative" // number: "singular" | "plural" // // Only the a-stem masculine paradigm is currently implemented; other stem classes // fall back to the nominative singular form. The corpus is small enough that // most attested nouns are a-stems or i-stems whose oblique forms can be // approximated by the a-stem pattern. fn peo_decline(noun: String, gram_case: String, number: String) -> String { return peo_decline_astem(noun, gram_case, number) } // ── peo_noun_phrase: noun phrase builder ────────────────────────────────────── // // Old Persian has no definite or indefinite articles. Definiteness was expressed // contextually or through word order, not morphologically. This function ignores // the "definite" parameter and returns the declined noun form directly. // // noun: Old Persian noun (nominative singular or stem) // gram_case: "nominative" | "accusative" | "genitive" | "dative" // number: "singular" | "plural" // definite: "true" | "false" (ignored — no articles in Old Persian) // // Returns the declined noun form. fn peo_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String { return peo_decline(noun, gram_case, number) }