use std::collections::BTreeMap;
use crate::conlang::morphology::paradigm;
use crate::conlang::types::morphology::{AgreementRule, Morphology};
use crate::conlang::types::Phonology;
#[derive(Debug, Clone)]
pub struct Agreement {
pub form: String,
pub gloss: String,
pub matched: BTreeMap<String, String>,
}
pub fn agree(
phon: &Phonology,
morph: &Morphology,
rule: &AgreementRule,
dependent_root: &str,
dependent_gloss: &str,
head_features: &BTreeMap<String, String>,
) -> Option<Agreement> {
let wanted: BTreeMap<String, String> = rule
.features
.iter()
.filter_map(|f| head_features.get(f).map(|v| (f.clone(), v.clone())))
.collect();
let template = morph.paradigm(&rule.paradigm)?;
let row = paradigm::realize_features(phon, morph, template, dependent_root, dependent_gloss, &wanted)?;
Some(Agreement { form: row.form, gloss: row.gloss, matched: wanted })
}
#[cfg(test)]
mod tests {
use super::*;
fn phon() -> Phonology {
let body = r#"{ phonemes: [
{ ipa: "k", kind: "consonant" }, { ipa: "t", kind: "consonant" },
{ ipa: "m", kind: "consonant" }, { ipa: "r", kind: "consonant" },
{ ipa: "a", kind: "vowel" }, { ipa: "i", kind: "vowel" }
] }"#;
Phonology::from_hjson(body).unwrap().unwrap()
}
fn morph() -> Morphology {
let body = r#"{
morphemes: [ { id: "pl", gloss: "PL", form: "i", position: "suffix" } ]
paradigms: [ { name: "adj", cells: [
{ features: { number: "sg" }, morphemes: [] }
{ features: { number: "pl" }, morphemes: ["pl"] }
] } ]
agreement: [
{ dependent: "adjective", head: "noun", features: ["number"], paradigm: "adj" }
]
}"#;
Morphology::from_hjson(body).unwrap().unwrap()
}
#[test]
fn adjective_agrees_with_plural_noun() {
let p = phon();
let m = morph();
let rule = m.agreement_for("adjective").unwrap();
let head: BTreeMap<String, String> =
[("number".to_string(), "pl".to_string())].into_iter().collect();
let a = agree(&p, &m, rule, "mira", "bright", &head).unwrap();
assert_eq!(a.form, "mirai"); assert_eq!(a.gloss, "bright-PL");
assert_eq!(a.matched.get("number").unwrap(), "pl");
}
#[test]
fn singular_head_gives_bare_form() {
let p = phon();
let m = morph();
let rule = m.agreement_for("adjective").unwrap();
let head: BTreeMap<String, String> =
[("number".to_string(), "sg".to_string())].into_iter().collect();
let a = agree(&p, &m, rule, "mira", "bright", &head).unwrap();
assert_eq!(a.form, "mira");
}
}