// semantics.el - Semantic layer: SemFrame -> GramSpec (slot map for realizer). // // Bridges from intent/meaning representation to the grammar layer. // A SemFrame is a slot map ([String] key-value list) with these keys: // // "intent" - "assert" | "query" | "describe" | "greet" // "subject" - subject referent (pronoun or noun phrase) // "object" - object referent (optional, "" if absent) // "modifiers" - semicolon-separated modifier strings (e.g. "in the park;quickly") // "lang" - ISO 639-1 language code (optional, defaults to "en") // // sem_to_spec converts a SemFrame into a realizer slot map ready for realize(). // sem_realize is the end-to-end shortcut: frame -> realized text. // // All existing function signatures are preserved; new *_lang variants add an // explicit lang_code parameter. // // Depends on: grammar (slots_*, realize), language-profile (lang_from_code) import "test_empty_gram.el" import "test_empty_gram.el" import "test_empty_gram.el" // ── SemFrame constructors ───────────────────────────────────────────────────── // Build a SemFrame with all four core fields. Language defaults to "en". fn sem_frame(intent: String, subject: String, obj: String, modifiers: String) -> [String] { let r: [String] = native_list_empty() let r = native_list_append(r, "intent") let r = native_list_append(r, intent) let r = native_list_append(r, "subject") let r = native_list_append(r, subject) let r = native_list_append(r, "object") let r = native_list_append(r, obj) let r = native_list_append(r, "modifiers") let r = native_list_append(r, modifiers) let r = native_list_append(r, "lang") let r = native_list_append(r, "en") return r } // Build a SemFrame with an explicit language code. fn sem_frame_lang(intent: String, subject: String, obj: String, modifiers: String, lang_code: String) -> [String] { let r: [String] = native_list_empty() let r = native_list_append(r, "intent") let r = native_list_append(r, intent) let r = native_list_append(r, "subject") let r = native_list_append(r, subject) let r = native_list_append(r, "object") let r = native_list_append(r, obj) let r = native_list_append(r, "modifiers") let r = native_list_append(r, modifiers) let r = native_list_append(r, "lang") let r = native_list_append(r, lang_code) return r } // Convenience: no object, no modifiers, English. fn sem_frame_simple(intent: String, subject: String) -> [String] { return sem_frame(intent, subject, "", "") } // Convenience: with object, no modifiers, English. fn sem_frame_obj(intent: String, subject: String, obj: String) -> [String] { return sem_frame(intent, subject, obj, "") } // ── SemFrame field accessors ────────────────────────────────────────────────── fn sem_intent(frame: [String]) -> String { return slots_get(frame, "intent") } fn sem_subject(frame: [String]) -> String { return slots_get(frame, "subject") } fn sem_object(frame: [String]) -> String { return slots_get(frame, "object") } fn sem_modifiers(frame: [String]) -> String { return slots_get(frame, "modifiers") } fn sem_lang(frame: [String]) -> String { let code: String = slots_get(frame, "lang") if str_eq(code, "") { return "en" } return code } // ── Modifier helpers ────────────────────────────────────────────────────────── fn sem_first_modifier(mods: String) -> String { let n: Int = str_len(mods) if n == 0 { return "" } let i: Int = 0 let running: Bool = true while running { if i >= n { let running = false } else { let c: String = str_slice(mods, i, i + 1) if str_eq(c, ";") { let running = false } else { let i = i + 1 } } } return str_slice(mods, 0, i) } // ── Intent mapping ──────────────────────────────────────────────────────────── fn sem_intent_to_realize(intent: String) -> String { if str_eq(intent, "assert") { return "assert" } if str_eq(intent, "query") { return "question" } if str_eq(intent, "describe") { return "assert" } if str_eq(intent, "greet") { return "greet" } return "assert" } // ── sem_to_spec: SemFrame -> realizer slot map ──────────────────────────────── // // The "lang" key from the SemFrame is forwarded into the GramSpec so that // realize() can resolve the correct language profile. fn sem_to_spec(frame: [String]) -> [String] { let intent: String = sem_intent(frame) let subject: String = sem_subject(frame) let obj: String = sem_object(frame) let mods: String = sem_modifiers(frame) let lang_code: String = sem_lang(frame) let location: String = sem_first_modifier(mods) if str_eq(intent, "greet") { let spec: [String] = native_list_empty() let spec = native_list_append(spec, "intent") let spec = native_list_append(spec, "greet") let spec = native_list_append(spec, "agent") let spec = native_list_append(spec, subject) let spec = native_list_append(spec, "predicate") let spec = native_list_append(spec, "") let spec = native_list_append(spec, "patient") let spec = native_list_append(spec, "") let spec = native_list_append(spec, "location") let spec = native_list_append(spec, "") let spec = native_list_append(spec, "tense") let spec = native_list_append(spec, "present") let spec = native_list_append(spec, "aspect") let spec = native_list_append(spec, "simple") let spec = native_list_append(spec, "lang") let spec = native_list_append(spec, lang_code) return spec } if str_eq(intent, "describe") { let spec: [String] = native_list_empty() let spec = native_list_append(spec, "intent") let spec = native_list_append(spec, "assert") let spec = native_list_append(spec, "agent") let spec = native_list_append(spec, subject) let spec = native_list_append(spec, "predicate") let spec = native_list_append(spec, "be") let spec = native_list_append(spec, "patient") let spec = native_list_append(spec, obj) let spec = native_list_append(spec, "location") let spec = native_list_append(spec, location) let spec = native_list_append(spec, "tense") let spec = native_list_append(spec, "present") let spec = native_list_append(spec, "aspect") let spec = native_list_append(spec, "simple") let spec = native_list_append(spec, "lang") let spec = native_list_append(spec, lang_code) return spec } let realize_intent: String = sem_intent_to_realize(intent) let spec: [String] = native_list_empty() let spec = native_list_append(spec, "intent") let spec = native_list_append(spec, realize_intent) let spec = native_list_append(spec, "agent") let spec = native_list_append(spec, subject) let spec = native_list_append(spec, "predicate") let spec = native_list_append(spec, obj) let spec = native_list_append(spec, "patient") let spec = native_list_append(spec, "") let spec = native_list_append(spec, "location") let spec = native_list_append(spec, location) let spec = native_list_append(spec, "tense") let spec = native_list_append(spec, "present") let spec = native_list_append(spec, "aspect") let spec = native_list_append(spec, "simple") let spec = native_list_append(spec, "lang") let spec = native_list_append(spec, lang_code) return spec } // ── sem_to_spec_full ────────────────────────────────────────────────────────── fn sem_to_spec_full(frame: [String], verb: String, tense: String, aspect: String) -> [String] { let intent: String = sem_intent(frame) let subject: String = sem_subject(frame) let obj: String = sem_object(frame) let mods: String = sem_modifiers(frame) let lang_code: String = sem_lang(frame) let location: String = sem_first_modifier(mods) if str_eq(intent, "greet") { return sem_to_spec(frame) } if str_eq(intent, "describe") { let spec: [String] = native_list_empty() let spec = native_list_append(spec, "intent") let spec = native_list_append(spec, "assert") let spec = native_list_append(spec, "agent") let spec = native_list_append(spec, subject) let spec = native_list_append(spec, "predicate") let spec = native_list_append(spec, "be") let spec = native_list_append(spec, "patient") let spec = native_list_append(spec, obj) let spec = native_list_append(spec, "location") let spec = native_list_append(spec, location) let spec = native_list_append(spec, "tense") let spec = native_list_append(spec, tense) let spec = native_list_append(spec, "aspect") let spec = native_list_append(spec, aspect) let spec = native_list_append(spec, "lang") let spec = native_list_append(spec, lang_code) return spec } let realize_intent: String = sem_intent_to_realize(intent) let spec: [String] = native_list_empty() let spec = native_list_append(spec, "intent") let spec = native_list_append(spec, realize_intent) let spec = native_list_append(spec, "agent") let spec = native_list_append(spec, subject) let spec = native_list_append(spec, "predicate") let spec = native_list_append(spec, verb) let spec = native_list_append(spec, "patient") let spec = native_list_append(spec, obj) let spec = native_list_append(spec, "location") let spec = native_list_append(spec, location) let spec = native_list_append(spec, "tense") let spec = native_list_append(spec, tense) let spec = native_list_append(spec, "aspect") let spec = native_list_append(spec, aspect) let spec = native_list_append(spec, "lang") let spec = native_list_append(spec, lang_code) return spec } // ── Greet realization helper ────────────────────────────────────────────────── fn sem_realize_greet(subject: String) -> String { if str_eq(subject, "") { return "Hello." } return "Hello, " + subject + "." } // ── sem_realize: SemFrame -> text ───────────────────────────────────────────── fn sem_realize(frame: [String]) -> String { let intent: String = sem_intent(frame) if str_eq(intent, "greet") { return sem_realize_greet(sem_subject(frame)) } let spec: [String] = sem_to_spec(frame) return realize(spec) } // ── sem_realize_full ────────────────────────────────────────────────────────── fn sem_realize_full(frame: [String], verb: String, tense: String, aspect: String) -> String { let intent: String = sem_intent(frame) if str_eq(intent, "greet") { return sem_realize_greet(sem_subject(frame)) } let spec: [String] = sem_to_spec_full(frame, verb, tense, aspect) return realize(spec) } // ── sem_realize_lang: realize in an explicitly specified language ────────────── // // Convenience for callers that want to specify the output language without // constructing a full SemFrame. The lang_code overrides whatever "lang" is // set in the frame. fn sem_realize_lang(frame: [String], lang_code: String) -> String { let intent: String = sem_intent(frame) if str_eq(intent, "greet") { return sem_realize_greet(sem_subject(frame)) } // Inject the lang_code into the frame before converting to spec. let patched: [String] = slots_set(frame, "lang", lang_code) let spec: [String] = sem_to_spec(patched) return realize(spec) }