354 lines
17 KiB
EmacsLisp
354 lines
17 KiB
EmacsLisp
// language-profile.el - Language profile data and accessors.
|
||
//
|
||
// A language profile is a slot map ([String] key-value list) describing the
|
||
// typological properties of a natural language. The engine reads these
|
||
// properties to drive morphology, word-order, and question-formation without
|
||
// any per-language code paths.
|
||
//
|
||
// Profile slot keys:
|
||
// code - ISO 639-1 code: "en", "ja", "ar", "zh", "de", "fr", "es", "sw", "hi", "ru", etc.
|
||
// word_order - "SVO" | "SOV" | "VSO" | "VOS" | "OVS" | "OSV" | "free"
|
||
// morph_type - "isolating" | "agglutinative" | "fusional" | "polysynthetic"
|
||
// has_case - "true" | "false"
|
||
// has_gender - "true" | "false"
|
||
// script_dir - "ltr" | "rtl" | "ttb"
|
||
// agreement - semicolon-separated features: "number;person" | "number;person;gender;case" | "none"
|
||
// null_subject - "true" | "false" (pro-drop: subject may be omitted)
|
||
|
||
// ── Constructor ───────────────────────────────────────────────────────────────
|
||
|
||
fn lang_profile(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String] {
|
||
let r: [String] = native_list_empty()
|
||
let r = native_list_append(r, "code")
|
||
let r = native_list_append(r, code)
|
||
let r = native_list_append(r, "word_order")
|
||
let r = native_list_append(r, word_order)
|
||
let r = native_list_append(r, "morph_type")
|
||
let r = native_list_append(r, morph_type)
|
||
let r = native_list_append(r, "has_case")
|
||
let r = native_list_append(r, has_case)
|
||
let r = native_list_append(r, "has_gender")
|
||
let r = native_list_append(r, has_gender)
|
||
let r = native_list_append(r, "script_dir")
|
||
let r = native_list_append(r, script_dir)
|
||
let r = native_list_append(r, "agreement")
|
||
let r = native_list_append(r, agreement)
|
||
let r = native_list_append(r, "null_subject")
|
||
let r = native_list_append(r, null_subject)
|
||
return r
|
||
}
|
||
|
||
// ── Accessor ──────────────────────────────────────────────────────────────────
|
||
|
||
fn lang_get(profile: [String], key: String) -> String {
|
||
let n: Int = native_list_len(profile)
|
||
let i: Int = 0
|
||
while i < n - 1 {
|
||
let k: String = native_list_get(profile, i)
|
||
if str_eq(k, key) {
|
||
return native_list_get(profile, i + 1)
|
||
}
|
||
let i = i + 2
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// ── Built-in profiles ─────────────────────────────────────────────────────────
|
||
//
|
||
// Each profile encodes typological facts about one language. These are data,
|
||
// not separate code paths. Adding a new language means adding a new profile
|
||
// and loading its vocabulary/suffix tables into the Engram - no engine changes.
|
||
|
||
// English: SVO, fusional, no grammatical case (nominative/accusative collapsed),
|
||
// no grammatical gender, left-to-right, agreement on number and person,
|
||
// obligatory subject (no pro-drop).
|
||
fn lang_profile_en() -> [String] {
|
||
return lang_profile("en", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||
}
|
||
|
||
// Japanese: SOV, agglutinative, grammatical relations marked by postpositions
|
||
// (not inflectional case), no grammatical gender, left-to-right, no agreement
|
||
// morphology on verbs, pro-drop (null subject frequent).
|
||
fn lang_profile_ja() -> [String] {
|
||
return lang_profile("ja", "SOV", "agglutinative", "false", "false", "ltr", "none", "true")
|
||
}
|
||
|
||
// Arabic: VSO, fusional, full case system, grammatical gender (masc/fem),
|
||
// right-to-left script, agreement on number, person, gender, and case,
|
||
// pro-drop (subject agreement marking on verb allows subject omission).
|
||
fn lang_profile_ar() -> [String] {
|
||
return lang_profile("ar", "VSO", "fusional", "true", "true", "rtl", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Mandarin Chinese: SVO, isolating (no morphological inflection), no case,
|
||
// no grammatical gender, left-to-right, no agreement (no morphological marking),
|
||
// null subject allowed in discourse context.
|
||
fn lang_profile_zh() -> [String] {
|
||
return lang_profile("zh", "SVO", "isolating", "false", "false", "ltr", "none", "true")
|
||
}
|
||
|
||
// German: V2 (second-position verb, base SOV in subordinate clauses), fusional,
|
||
// four-case system, three grammatical genders, left-to-right, agreement on
|
||
// number, person, gender, and case, obligatory subject.
|
||
fn lang_profile_de() -> [String] {
|
||
return lang_profile("de", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// Spanish: SVO, fusional, no morphological case (but object clitics exist),
|
||
// grammatical gender (masc/fem), left-to-right, agreement on number, person,
|
||
// and gender, pro-drop (rich verbal agreement allows subject omission).
|
||
fn lang_profile_es() -> [String] {
|
||
return lang_profile("es", "SVO", "fusional", "false", "true", "ltr", "number;person;gender", "true")
|
||
}
|
||
|
||
// Finnish: SOV, agglutinative, fifteen grammatical cases, no grammatical gender,
|
||
// left-to-right, agreement on number, person, and case, no pro-drop (subject
|
||
// required in finite clauses).
|
||
fn lang_profile_fi() -> [String] {
|
||
return lang_profile("fi", "SOV", "agglutinative", "true", "false", "ltr", "number;person;case", "false")
|
||
}
|
||
|
||
// Swahili: SVO, agglutinative, noun-class system (15+ classes replacing gender),
|
||
// no case inflection, left-to-right, agreement driven by noun class and number,
|
||
// pro-drop (subject prefix on verb can stand alone).
|
||
fn lang_profile_sw() -> [String] {
|
||
return lang_profile("sw", "SVO", "agglutinative", "false", "false", "ltr", "noun-class;number", "true")
|
||
}
|
||
|
||
// Hindi: SOV, fusional, case-marked postpositional system, grammatical gender
|
||
// (masc/fem), left-to-right (Devanagari script still ltr), agreement on number,
|
||
// person, gender, and case, pro-drop (subject frequently dropped).
|
||
fn lang_profile_hi() -> [String] {
|
||
return lang_profile("hi", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Russian: free word order (pragmatically determined), fusional, six-case system,
|
||
// three grammatical genders, left-to-right (Cyrillic), agreement on number,
|
||
// person, gender, and case, no pro-drop (subject required).
|
||
fn lang_profile_ru() -> [String] {
|
||
return lang_profile("ru", "free", "fusional", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// French: SVO, fusional, no morphological case (but clitic object pronouns),
|
||
// two grammatical genders (masc/fem), left-to-right, agreement on number,
|
||
// person, and gender, no pro-drop.
|
||
fn lang_profile_fr() -> [String] {
|
||
return lang_profile("fr", "SVO", "fusional", "false", "true", "ltr", "number;person;gender", "false")
|
||
}
|
||
|
||
// Latin: SOV (highly free word order), fusional, six-case system (nom/gen/dat/acc/abl/voc),
|
||
// three genders (masc/fem/neut), left-to-right, rich agreement on number, person, gender,
|
||
// and case, pro-drop (subject expressed in verb ending).
|
||
fn lang_profile_la() -> [String] {
|
||
return lang_profile("la", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Hebrew (Modern): SVO, Semitic trilateral root morphology, two genders (masc/fem),
|
||
// two numbers (singular/plural; dual vestigial), right-to-left (Hebrew script),
|
||
// agreement on number, person, gender; zero copula in present tense; no grammatical cases.
|
||
fn lang_profile_he() -> [String] {
|
||
return lang_profile("he", "SVO", "semitic", "true", "false", "rtl", "number;person;gender", "true")
|
||
}
|
||
|
||
// Sanskrit: SOV/free, highly fusional, 3 genders, 8 cases, 3 numbers (sg/du/pl),
|
||
// Devanagari script, rich verb system (10 classes, 9 tenses/moods), pro-drop.
|
||
fn lang_profile_sa() -> [String] {
|
||
return lang_profile("sa", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Gothic: SOV, fusional, 3 genders, 4 cases, singular/plural,
|
||
// Gothic alphabet (romanized as þ/ƕ/ai/au/ei), strong and weak classes, pro-drop.
|
||
fn lang_profile_got() -> [String] {
|
||
return lang_profile("got", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Old Norse: free/SOV, fusional, 3 genders, 4 cases, singular/plural,
|
||
// definite article as noun suffix (-inn/-in/-it), strong and weak classes, pro-drop.
|
||
fn lang_profile_non() -> [String] {
|
||
return lang_profile("non", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Middle English (ca. 1100–1500): SVO emerging, mostly lost case system,
|
||
// -es plural/genitive, strong and weak verbs, no grammatical gender on nouns.
|
||
fn lang_profile_enm() -> [String] {
|
||
return lang_profile("enm", "SVO", "fusional", "false", "false", "ltr", "number;person", "false")
|
||
}
|
||
|
||
// Pali: SOV, fusional (simplified Sanskrit), 3 genders, 8 cases, sg/pl,
|
||
// Latin transliteration with IAST diacritics, Buddhist canonical language.
|
||
fn lang_profile_pi() -> [String] {
|
||
return lang_profile("pi", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Ancient Greek: free/SOV word order, highly fusional, 3 genders, 5 cases (nom/acc/gen/dat/voc),
|
||
// singular/dual/plural, polytonic Greek script (Unicode), complex verb system with aspect
|
||
// (imperfective/perfective), augment in past tenses, pro-drop.
|
||
fn lang_profile_grc() -> [String] {
|
||
return lang_profile("grc", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case;aspect", "true")
|
||
}
|
||
|
||
// Old English (Anglo-Saxon): SOV/V2, fusional, 3 genders, 4 cases (nom/acc/gen/dat),
|
||
// singular/plural, Latin alphabet + þ/ð/ƿ/æ, strong and weak noun/verb classes, pro-drop.
|
||
fn lang_profile_ang() -> [String] {
|
||
return lang_profile("ang", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Old French (ca. 1000–1300 CE): SVO/V2, fusional, two-case system (nominative/oblique),
|
||
// two genders (masculine/feminine), left-to-right, agreement on number, person, gender,
|
||
// and case, no pro-drop (subject generally required).
|
||
fn lang_profile_fro() -> [String] {
|
||
return lang_profile("fro", "SVO", "fusional", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// Old High German (ca. 750–1050 CE): SOV/V2, fusional, four-case system, three genders,
|
||
// left-to-right, agreement on number, person, gender, and case, pro-drop.
|
||
fn lang_profile_goh() -> [String] {
|
||
return lang_profile("goh", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Old Irish (ca. 600–900 CE): VSO, fusional, case system, three genders,
|
||
// left-to-right, agreement on number, person, gender, and case, pro-drop.
|
||
fn lang_profile_sga() -> [String] {
|
||
return lang_profile("sga", "VSO", "fusional", "true", "true", "ltr", "number;person;gender;case", "true")
|
||
}
|
||
|
||
// Tocharian B (ca. 500–1000 CE): SOV, fusional, case system, two genders,
|
||
// left-to-right, agreement on number, person, gender, and case, no pro-drop.
|
||
fn lang_profile_txb() -> [String] {
|
||
return lang_profile("txb", "SOV", "fusional", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// Old Persian (ca. 525–330 BCE): SOV, fusional, 8-case system, no grammatical gender,
|
||
// left-to-right, agreement on number, person, and case, pro-drop.
|
||
fn lang_profile_peo() -> [String] {
|
||
return lang_profile("peo", "SOV", "fusional", "true", "false", "ltr", "number;person;case", "true")
|
||
}
|
||
|
||
// Akkadian (Old Babylonian period, ca. 1900–1600 BCE): VSO, fusional, 3-case system
|
||
// (nominative/accusative/genitive with mimation), two genders, left-to-right,
|
||
// agreement on number, person, gender, and case, no pro-drop.
|
||
fn lang_profile_akk() -> [String] {
|
||
return lang_profile("akk", "VSO", "fusional", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// Ugaritic (ca. 1400–1200 BCE): VSO, Semitic trilateral root morphology, 3-case system,
|
||
// two genders, left-to-right (cuneiform alphabetic script), agreement on number, person,
|
||
// gender, and case, no pro-drop.
|
||
fn lang_profile_uga() -> [String] {
|
||
return lang_profile("uga", "VSO", "semitic", "true", "true", "ltr", "number;person;gender;case", "false")
|
||
}
|
||
|
||
// Ancient Egyptian / Middle Egyptian (ca. 2100–1300 BCE): SVO, agglutinative,
|
||
// no morphological case (word order + prepositions), two genders, left-to-right,
|
||
// agreement on number, person, and gender, pro-drop (zero copula in present).
|
||
fn lang_profile_egy() -> [String] {
|
||
return lang_profile("egy", "SVO", "agglutinative", "false", "true", "ltr", "number;person;gender", "true")
|
||
}
|
||
|
||
// Sumerian (ca. 3000–2000 BCE): SOV, agglutinative, ergative-absolutive case system,
|
||
// no grammatical gender (animacy distinction instead), left-to-right, agreement on
|
||
// number and person, pro-drop.
|
||
fn lang_profile_sux() -> [String] {
|
||
return lang_profile("sux", "SOV", "agglutinative", "true", "false", "ltr", "number;person", "true")
|
||
}
|
||
|
||
// Ge'ez (Classical Ethiopic, ca. 4th–7th century CE): SOV, Semitic trilateral root
|
||
// morphology, two genders (masc/fem), Ethiopic/Fidel script (ltr), agreement on
|
||
// number, person, and gender, pro-drop (subject inflection on verb).
|
||
fn lang_profile_gez() -> [String] {
|
||
return lang_profile("gez", "SOV", "semitic", "true", "true", "ltr", "number;person;gender", "true")
|
||
}
|
||
|
||
// Coptic (Sahidic dialect, ca. 3rd–11th century CE): SVO, agglutinative, no
|
||
// morphological case, two genders (masc/fem), left-to-right (Coptic alphabet),
|
||
// agreement on number and gender via bound subject pronouns, no pro-drop (explicit
|
||
// subject prefix required on every verb).
|
||
fn lang_profile_cop() -> [String] {
|
||
return lang_profile("cop", "SVO", "agglutinative", "false", "true", "ltr", "number;person;gender", "false")
|
||
}
|
||
|
||
// ── Dispatch: code -> profile ─────────────────────────────────────────────────
|
||
|
||
fn lang_from_code(code: String) -> [String] {
|
||
if str_eq(code, "en") { return lang_profile_en() }
|
||
if str_eq(code, "ja") { return lang_profile_ja() }
|
||
if str_eq(code, "ar") { return lang_profile_ar() }
|
||
if str_eq(code, "zh") { return lang_profile_zh() }
|
||
if str_eq(code, "de") { return lang_profile_de() }
|
||
if str_eq(code, "es") { return lang_profile_es() }
|
||
if str_eq(code, "fi") { return lang_profile_fi() }
|
||
if str_eq(code, "sw") { return lang_profile_sw() }
|
||
if str_eq(code, "hi") { return lang_profile_hi() }
|
||
if str_eq(code, "ru") { return lang_profile_ru() }
|
||
if str_eq(code, "fr") { return lang_profile_fr() }
|
||
if str_eq(code, "la") { return lang_profile_la() }
|
||
if str_eq(code, "he") { return lang_profile_he() }
|
||
if str_eq(code, "grc") { return lang_profile_grc() }
|
||
if str_eq(code, "ang") { return lang_profile_ang() }
|
||
if str_eq(code, "sa") { return lang_profile_sa() }
|
||
if str_eq(code, "got") { return lang_profile_got() }
|
||
if str_eq(code, "non") { return lang_profile_non() }
|
||
if str_eq(code, "enm") { return lang_profile_enm() }
|
||
if str_eq(code, "pi") { return lang_profile_pi() }
|
||
if str_eq(code, "fro") { return lang_profile_fro() }
|
||
if str_eq(code, "goh") { return lang_profile_goh() }
|
||
if str_eq(code, "sga") { return lang_profile_sga() }
|
||
if str_eq(code, "txb") { return lang_profile_txb() }
|
||
if str_eq(code, "peo") { return lang_profile_peo() }
|
||
if str_eq(code, "akk") { return lang_profile_akk() }
|
||
if str_eq(code, "uga") { return lang_profile_uga() }
|
||
if str_eq(code, "egy") { return lang_profile_egy() }
|
||
if str_eq(code, "sux") { return lang_profile_sux() }
|
||
if str_eq(code, "gez") { return lang_profile_gez() }
|
||
if str_eq(code, "cop") { return lang_profile_cop() }
|
||
// Unknown code: fall back to English profile
|
||
return lang_profile_en()
|
||
}
|
||
|
||
// English default - backward compatibility entry point.
|
||
fn lang_default() -> [String] {
|
||
return lang_profile_en()
|
||
}
|
||
|
||
// ── Typed convenience predicates ──────────────────────────────────────────────
|
||
|
||
fn lang_is_isolating(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "morph_type"), "isolating")
|
||
}
|
||
|
||
fn lang_is_agglutinative(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "morph_type"), "agglutinative")
|
||
}
|
||
|
||
fn lang_is_fusional(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "morph_type"), "fusional")
|
||
}
|
||
|
||
fn lang_is_polysynthetic(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "morph_type"), "polysynthetic")
|
||
}
|
||
|
||
fn lang_is_rtl(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "script_dir"), "rtl")
|
||
}
|
||
|
||
fn lang_has_null_subject(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "null_subject"), "true")
|
||
}
|
||
|
||
fn lang_has_case(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "has_case"), "true")
|
||
}
|
||
|
||
fn lang_has_gender(profile: [String]) -> Bool {
|
||
return str_eq(lang_get(profile, "has_gender"), "true")
|
||
}
|
||
|
||
fn lang_word_order(profile: [String]) -> String {
|
||
return lang_get(profile, "word_order")
|
||
}
|
||
|
||
fn lang_code(profile: [String]) -> String {
|
||
return lang_get(profile, "code")
|
||
}
|