// morphology-akk.el - Akkadian morphology for the NLG engine. // π’€­π’‚—π’ͺ β€” Akkadian (akkadΓ»), the language of Babylon and Assyria. // // Implements Old Babylonian Akkadian verb conjugation (G-stem / Grundstamm), // noun declension with mimation, and noun-phrase construction. // // Akkadian is the oldest attested Semitic language (ca. 2800–100 BCE). // It uses cuneiform script; we work in standard Latin transliteration // (Old Babylonian dialect β€” the classical prestige form). // // Language profile: // code=akk, name=Akkadian, morph_type=semitic, word_order=VSO/SOV, // script=cuneiform (transliterated), family=semitic/east-semitic // // Key grammatical facts: // - Semitic trilateral root system: words built from 3-consonant roots // by inserting vowel patterns (e.g. root p-r-s β†’ iparras "he decides") // - Grammatical gender: masculine / feminine (no neuter) // - Cases: nominative (-um), accusative (-am), genitive (-im) β€” "mimation" // - Number: singular / plural (dual is vestigial in verbs) // - Verb stems: G (basic), D (intensive), Ε  (causative), N (passive); // this file implements G-stem throughout // - Two main tense/aspect systems: // Present-future (iparras pattern): action in progress or future // Perfect (iptaras pattern): completed action with present relevance // Stative (paris pattern): resultant state, often adjectival // - No definite or indefinite article; case endings convey // determination contextually // - Copula: baΕ‘Γ» (to exist/be) // // Verb conjugation conventions: // person: "first" | "second" | "third" // gender: "m" | "f" // number: "singular" | "plural" // tense: "present" | "perfect" | "stative" // // Noun declension conventions: // gram_case: "nom" | "acc" | "gen" // number: "singular" | "plural" // gender: "m" | "f" (passed to akk_decline for gender-specific forms) // // Verbs covered (G-stem infinitive, transliterated): // "baΕ‘Γ»" β€” to exist / be (copula) // "alāku" β€” to go // "amāru" β€” to see // "qabΓ»" β€” to say // "epΔ“Ε‘u" β€” to do / make // // Nouns covered with known mimation forms: // "Ε‘arrum" β€” king // "awΔ«lum" β€” man / person // "bΔ«tum" β€” house // "ilum" β€” god // // Depends on: morphology.el (str_eq, str_len, str_slice, str_ends_with) // ── String helpers ───────────────────────────────────────────────────────────── import "morphology.el" fn akk_str_ends(s: String, suf: String) -> Bool { return str_ends_with(s, suf) } fn akk_str_len(s: String) -> Int { return str_len(s) } fn akk_str_drop_last(s: String, n: Int) -> String { let len: Int = str_len(s) if n >= len { return "" } return str_slice(s, 0, len - n) } // ── Slot index ───────────────────────────────────────────────────────────────── // // Maps person Γ— number to a 0-based slot for table lookups. // Akkadian verb agreement does not distinguish gender in 1st person, // and the 2nd person often conflates masc/fem in some paradigms. // We use a 6-cell paradigm matching the most common OB presentation: // // 0 = 1sg (I) // 1 = 2sg (you sg) // 2 = 3sg m (he) // 3 = 3sg f (she) // 4 = 1pl (we) // 5 = 3pl (they) // // Note: 2pl is rare / vestigial in attested OB texts; omitted here. fn akk_slot(person: String, number: String) -> Int { if str_eq(person, "first") { if str_eq(number, "plural") { return 4 } return 0 } if str_eq(person, "second") { return 1 } // third if str_eq(number, "plural") { return 5 } return 2 // default: 3sg masc; caller may override with gender check below } // akk_slot_g: gender-aware slot for third person singular. // Returns 3 (3sg fem) when person=third, number=singular, gender=f. fn akk_slot_g(person: String, gender: String, number: String) -> Int { let base: Int = akk_slot(person, number) if str_eq(person, "third") { if str_eq(number, "singular") { if str_eq(gender, "f") { return 3 } } } return base } // ── Copula: baΕ‘Γ» β€” to exist / be ────────────────────────────────────────────── // // baΕ‘Γ» is suppletive and highly irregular. // Present: ibaΕ‘Ε‘i (3sg m/f), abaΕ‘Ε‘i (1sg), tabaΕ‘Ε‘i (2sg) // Stative: baΕ‘Δ« (3sg m), baΕ‘iat (3sg f), baőāku (1sg) // Perfect: not commonly attested in G-stem; use present forms as fallback. fn akk_copula_present(slot: Int) -> String { if slot == 0 { return "abaΕ‘Ε‘i" } // 1sg if slot == 1 { return "tabaΕ‘Ε‘i" } // 2sg if slot == 2 { return "ibaΕ‘Ε‘i" } // 3sg m if slot == 3 { return "ibaΕ‘Ε‘i" } // 3sg f (same form in attested OB) if slot == 4 { return "nibaΕ‘Ε‘i" } // 1pl return "ibaΕ‘Ε‘Ε«" // 3pl } fn akk_copula_stative(slot: Int) -> String { if slot == 0 { return "baőāku" } // 1sg (stative 1sg: -āku suffix) if slot == 1 { return "baőāta" } // 2sg (-āta suffix) if slot == 2 { return "baΕ‘Δ«" } // 3sg m (unmarked base) if slot == 3 { return "baΕ‘iat" } // 3sg f (-at suffix) if slot == 4 { return "baőānu" } // 1pl (-ānu suffix) return "baΕ‘Ε«" // 3pl (-Ε« suffix) } fn akk_is_copula(verb: String) -> Bool { if str_eq(verb, "baΕ‘Γ»") { return true } if str_eq(verb, "bashu") { return true } if str_eq(verb, "be") { return true } return false } fn akk_conjugate_copula(tense: String, slot: Int) -> String { if str_eq(tense, "stative") { return akk_copula_stative(slot) } // present and perfect both fall back to present forms for baΕ‘Γ» return akk_copula_present(slot) } // ── alāku β€” to go ───────────────────────────────────────────────────────────── // // Irregular: present stem is illak- (not the expected alakk-). // Present: illak (3sg), allak (1sg), tallak (2sg), nillak (1pl), illaku (3pl) // Perfect: ittalk- forms (less common, use illak- + perf marker) // Stative: use present as proxy fn akk_alaku_present(slot: Int) -> String { if slot == 0 { return "allak" } // 1sg if slot == 1 { return "tallak" } // 2sg if slot == 2 { return "illak" } // 3sg m if slot == 3 { return "tallak" } // 3sg f (same as 2sg β€” OB pattern) if slot == 4 { return "nillak" } // 1pl return "illaku" // 3pl } fn akk_alaku_perfect(slot: Int) -> String { if slot == 0 { return "ittalak" } // 1sg if slot == 1 { return "tattalak" } // 2sg if slot == 2 { return "ittalak" } // 3sg m if slot == 3 { return "tattalak" } // 3sg f if slot == 4 { return "nittalak" } // 1pl return "ittalku" // 3pl } // ── amāru β€” to see ──────────────────────────────────────────────────────────── // // Present (immar-): immar (3sg), ammar (1sg), tammar (2sg) // Perfect (imtamar-): imtamar (3sg), amtamar (1sg), tamtamar (2sg) fn akk_amaru_present(slot: Int) -> String { if slot == 0 { return "ammar" } // 1sg if slot == 1 { return "tammar" } // 2sg if slot == 2 { return "immar" } // 3sg m if slot == 3 { return "tammar" } // 3sg f if slot == 4 { return "nimmar" } // 1pl return "immaru" // 3pl } fn akk_amaru_perfect(slot: Int) -> String { if slot == 0 { return "amtamar" } // 1sg if slot == 1 { return "tamtamar" } // 2sg if slot == 2 { return "imtamar" } // 3sg m if slot == 3 { return "tamtamar" } // 3sg f if slot == 4 { return "nimtamar" } // 1pl return "imtamaru" // 3pl } fn akk_amaru_stative(slot: Int) -> String { // amāru stative: 3sg "amir" (the one who saw / he has seen) if slot == 0 { return "amrāku" } if slot == 1 { return "amrāta" } if slot == 2 { return "amir" } if slot == 3 { return "amrat" } if slot == 4 { return "amrānu" } return "amrΕ«" } // ── qabΓ» β€” to say / speak ───────────────────────────────────────────────────── // // Present: iqabbi (3sg), aqabbi (1sg), taqabbi (2sg) // Perfect: iqtabi (3sg), aqtabi (1sg), taqtabi (2sg) fn akk_qabu_present(slot: Int) -> String { if slot == 0 { return "aqabbi" } // 1sg if slot == 1 { return "taqabbi" } // 2sg if slot == 2 { return "iqabbi" } // 3sg m if slot == 3 { return "taqabbi" } // 3sg f if slot == 4 { return "niqabbi" } // 1pl return "iqabbΓ»" // 3pl } fn akk_qabu_perfect(slot: Int) -> String { if slot == 0 { return "aqtabi" } // 1sg if slot == 1 { return "taqtabi" } // 2sg if slot == 2 { return "iqtabi" } // 3sg m if slot == 3 { return "taqtabi" } // 3sg f if slot == 4 { return "niqtabi" } // 1pl return "iqtabΓ»" // 3pl } fn akk_qabu_stative(slot: Int) -> String { if slot == 0 { return "qabāku" } if slot == 1 { return "qabāta" } if slot == 2 { return "qabi" } if slot == 3 { return "qabiat" } if slot == 4 { return "qabānu" } return "qabΓ»" } // ── epΔ“Ε‘u β€” to do / make ────────────────────────────────────────────────────── // // Present (ieppuΕ‘ / eppuΕ‘): ieppuΕ‘ (3sg), eppuΕ‘ (1sg), teppuΕ‘ (2sg) // Perfect: ipteΕ‘u forms fn akk_epesu_present(slot: Int) -> String { if slot == 0 { return "eppuΕ‘" } // 1sg if slot == 1 { return "teppuΕ‘" } // 2sg if slot == 2 { return "ieppuΕ‘" } // 3sg m if slot == 3 { return "teppuΕ‘" } // 3sg f if slot == 4 { return "neppuΕ‘" } // 1pl return "ieppuΕ‘u" // 3pl } fn akk_epesu_perfect(slot: Int) -> String { if slot == 0 { return "ipteΕ‘u" } // 1sg (irregular: root ΚΏ-p-Ε‘) if slot == 1 { return "tapteΕ‘u" } // 2sg if slot == 2 { return "ipteΕ‘u" } // 3sg m if slot == 3 { return "tapteΕ‘u" } // 3sg f if slot == 4 { return "nipteΕ‘u" } // 1pl return "ipteΕ‘Ε«" // 3pl } fn akk_epesu_stative(slot: Int) -> String { if slot == 0 { return "epőāku" } if slot == 1 { return "epőāta" } if slot == 2 { return "epuΕ‘" } if slot == 3 { return "epΕ‘at" } if slot == 4 { return "epőānu" } return "epΕ‘Ε«" } // ── Regular G-stem paradigms (iparras model) ────────────────────────────────── // // For regular verbs not in the irregular table, we apply the standard // OB G-stem paradigm using a caller-supplied present stem and perfect stem. // The stems must be pre-computed by the caller (or vocabulary layer). // // iparras (present) endings by slot: // 1sg: a- prefix // 2sg: ta- prefix // 3sg m: i- prefix // 3sg f: ta- prefix (same prefix as 2sg) // 1pl: ni- prefix // 3pl: i- prefix + -Ε« suffix // // For the generic fallback we use "iparras" as the model template. fn akk_regular_present(stem: String, slot: Int) -> String { // stem is the 3sg m form (i-prefix already present in conventional citation) // We rebuild from the bare root portion by stripping/adding prefixes. // Simplification: return prefixed forms using the provided present-3sg string. if slot == 0 { return "a" + stem } // 1sg: a + stem (strip i-, add a-) if slot == 1 { return "ta" + stem } // 2sg if slot == 2 { return "i" + stem } // 3sg m if slot == 3 { return "ta" + stem } // 3sg f if slot == 4 { return "ni" + stem } // 1pl return "i" + stem + "u" // 3pl: i + stem + -Ε« } fn akk_regular_perfect(stem: String, slot: Int) -> String { // Perfect (iptaras) β€” uses infix -ta- after first root consonant. // stem here is the 3sg perfect form; we apply person endings. if slot == 0 { return "a" + stem } // 1sg if slot == 1 { return "ta" + stem } // 2sg if slot == 2 { return "i" + stem } // 3sg m if slot == 3 { return "ta" + stem } // 3sg f if slot == 4 { return "ni" + stem } // 1pl return "i" + stem + "u" // 3pl } fn akk_regular_stative(stem: String, slot: Int) -> String { // Stative (paris): 3sg m has zero ending; others take person suffixes. if slot == 0 { return stem + "āku" } // 1sg if slot == 1 { return stem + "āta" } // 2sg if slot == 2 { return stem } // 3sg m: bare stem if slot == 3 { return stem + "at" } // 3sg f if slot == 4 { return stem + "ānu" } // 1pl return stem + "Ε«" // 3pl } // ── Known-verb dispatcher ───────────────────────────────────────────────────── fn akk_known_verb(verb: String, tense: String, slot: Int) -> String { // baΕ‘Γ» β€” to be / exist if str_eq(verb, "baΕ‘Γ»") { return akk_conjugate_copula(tense, slot) } if str_eq(verb, "bashu") { return akk_conjugate_copula(tense, slot) } // alāku β€” to go if str_eq(verb, "alāku") { if str_eq(tense, "perfect") { return akk_alaku_perfect(slot) } if str_eq(tense, "stative") { return akk_alaku_present(slot) } return akk_alaku_present(slot) } if str_eq(verb, "alaku") { if str_eq(tense, "perfect") { return akk_alaku_perfect(slot) } return akk_alaku_present(slot) } // amāru β€” to see if str_eq(verb, "amāru") { if str_eq(tense, "perfect") { return akk_amaru_perfect(slot) } if str_eq(tense, "stative") { return akk_amaru_stative(slot) } return akk_amaru_present(slot) } if str_eq(verb, "amaru") { if str_eq(tense, "perfect") { return akk_amaru_perfect(slot) } if str_eq(tense, "stative") { return akk_amaru_stative(slot) } return akk_amaru_present(slot) } // qabΓ» β€” to say if str_eq(verb, "qabΓ»") { if str_eq(tense, "perfect") { return akk_qabu_perfect(slot) } if str_eq(tense, "stative") { return akk_qabu_stative(slot) } return akk_qabu_present(slot) } if str_eq(verb, "qabu") { if str_eq(tense, "perfect") { return akk_qabu_perfect(slot) } if str_eq(tense, "stative") { return akk_qabu_stative(slot) } return akk_qabu_present(slot) } // epΔ“Ε‘u β€” to do / make if str_eq(verb, "epΔ“Ε‘u") { if str_eq(tense, "perfect") { return akk_epesu_perfect(slot) } if str_eq(tense, "stative") { return akk_epesu_stative(slot) } return akk_epesu_present(slot) } if str_eq(verb, "epesu") { if str_eq(tense, "perfect") { return akk_epesu_perfect(slot) } if str_eq(tense, "stative") { return akk_epesu_stative(slot) } return akk_epesu_present(slot) } return "" } // ── Main conjugation entry point ────────────────────────────────────────────── // // akk_conjugate: conjugate an Akkadian verb (G-stem). // // verb: G-stem infinitive (transliterated, e.g. "alāku", "amāru") // tense: "present" | "perfect" | "stative" // person: "first" | "second" | "third" // number: "singular" | "plural" // // Returns: // - Inflected form for known verbs // - verb unchanged as safe fallback for unknown verbs fn akk_conjugate(verb: String, tense: String, person: String, number: String) -> String { let slot: Int = akk_slot(person, number) // Copula shortcut if akk_is_copula(verb) { return akk_conjugate_copula(tense, slot) } // Known-verb table let known: String = akk_known_verb(verb, tense, slot) if !str_eq(known, "") { return known } // Unknown verb: safe fallback return verb } // ── Noun declension ──────────────────────────────────────────────────────────── // // akk_decline: decline an Akkadian noun for gram_case and number. // // Mimation: OB nouns bear final -m in all case endings (mimation). // The base noun (dictionary form) is the nominative singular with mimation. // We strip the nominative -um ending (if present) to obtain the bare stem, // then apply the requested ending. // // Masculine case endings (singular): // Nominative: -um // Accusative: -am // Genitive: -im // // Masculine case endings (plural): // Nominative: -Ε«tum (or -Ε« in construct) // Accusative/Genitive: -ātim (or -Δ« in construct) // // Feminine nouns (identified by -tum nom sg ending): // Sg nominative: -tum, accusative: -tam, genitive: -tim // Pl nominative: -ātum, genitive/accusative: -ātim // // Known irregular stems (the vocabulary layer should pass dictionary forms): // Ε‘arrum β†’ stem: Ε‘arr- // awΔ«lum β†’ stem: awΔ«l- // bΔ«tum β†’ stem: bΔ«t- // ilum β†’ stem: il- fn akk_strip_nom(noun: String) -> String { // Strip -um (masc nom sg mimation ending) to get bare stem if akk_str_ends(noun, "um") { return akk_str_drop_last(noun, 2) } // Strip -tum (fem nom sg) if akk_str_ends(noun, "tum") { return akk_str_drop_last(noun, 3) } // Already a bare stem or unusual form: return as-is return noun } fn akk_is_fem(noun: String) -> Bool { // Feminine nouns in OB typically end in -tum (nom sg) if akk_str_ends(noun, "tum") { return true } if akk_str_ends(noun, "tam") { return true } if akk_str_ends(noun, "tim") { return true } return false } fn akk_decline(noun: String, gram_case: String, number: String) -> String { let fem: Bool = akk_is_fem(noun) let stem: String = akk_strip_nom(noun) if str_eq(number, "singular") { if fem { if str_eq(gram_case, "nom") { return stem + "tum" } if str_eq(gram_case, "acc") { return stem + "tam" } if str_eq(gram_case, "gen") { return stem + "tim" } return stem + "tum" } // Masculine if str_eq(gram_case, "nom") { return stem + "um" } if str_eq(gram_case, "acc") { return stem + "am" } if str_eq(gram_case, "gen") { return stem + "im" } return stem + "um" } // Plural if fem { if str_eq(gram_case, "nom") { return stem + "ātum" } // acc and gen merge in the oblique plural return stem + "ātim" } // Masculine plural if str_eq(gram_case, "nom") { return stem + "Ε«tum" } return stem + "ātim" } // ── Noun phrase ──────────────────────────────────────────────────────────────── // // akk_noun_phrase: produce the surface noun phrase. // // Akkadian has no definite or indefinite article. Determination is conveyed // by context, word order, and the genitive construct chain (status constructus). // The definite parameter is accepted but has no surface effect: the declined // noun is returned in either case. // // noun: dictionary form (nominative singular with mimation, e.g. "Ε‘arrum") // gram_case: "nom" | "acc" | "gen" // number: "singular" | "plural" // definite: "true" | "false" (no surface effect in Akkadian) fn akk_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String { return akk_decline(noun, gram_case, number) } // ── Canonical verb mapping ───────────────────────────────────────────────────── // // akk_map_canonical: map cross-lingual English canonical verb labels to // their Akkadian G-stem infinitive equivalents. fn akk_map_canonical(verb: String) -> String { if str_eq(verb, "be") { return "baΕ‘Γ»" } if str_eq(verb, "go") { return "alāku" } if str_eq(verb, "see") { return "amāru" } if str_eq(verb, "say") { return "qabΓ»" } if str_eq(verb, "speak") { return "qabΓ»" } if str_eq(verb, "do") { return "epΔ“Ε‘u" } if str_eq(verb, "make") { return "epΔ“Ε‘u" } return verb }