90ddbdbfc3
Brings the remaining foundation repos that were not included in the original monorepo consolidation: - arbor/vessels/ — 6 vessels (arbor-cli, arbor-core, arbor-diagram, arbor-layout, arbor-parse, arbor-render) with manifests + src/main.el - dharma/ — CGI Provenance Registry package (flat layout, 14 .el files across registry/, sandbox/, training/, validation/, tests/) - forge/ — consciousness channel tool (8 src .el files + new manifest.el) - elp/src/ — 36 test fixture files not carried over in original merge (dedup_*, realizer_*, semantics_*, morph_*, ext_*, one_extern_* helpers) el-ide, engram, elql are already complete in ide/, engram/, ql/.
312 lines
12 KiB
EmacsLisp
312 lines
12 KiB
EmacsLisp
// 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)
|
|
}
|