// surface-profile.el - Surface profile data and accessors. // // THE NATIVE EFFERENT SEAM: surface = a pluggable PROFILE, using the exact same // slot-map mechanism as language-profile.el. A language profile tells the // realizer HOW to shape a natural-language surface (word order, morphology); a // SURFACE profile tells the realizer WHICH surface to project meaning onto // (markdown, docx, html, plain, or a non-text medium like symbolic music). // // The generalization is exact: realize_lang(form, profile) already renders a // SemForm parameterized by a [String] profile read via lang_get. Surface is one // more axis of that same profile vector. One frame (sem_frame), one plan step // (sem_to_spec), one render (realize) — the surface is DATA, not a code path, // precisely as language is data. Adding a surface means adding a profile, no // engine change. This is the multimodal projector, native: geometry -> any // surface, the efferent twin of ingest. // // Surface slot keys: // surface - "markdown" | "docx" | "html" | "plain" | "midi" | "image" // modality - "text" | "audio" | "image" | "video" // media_type - MIME type of the emitted surface // head_open - string prepended to a heading (e.g. "## " for markdown) // head_close - string appended to a heading (e.g. "" for markdown, "" for html) // emph_open - string opening emphasis (e.g. "*") // emph_close - string closing emphasis (e.g. "*") // item_mark - list-item marker (e.g. "- ") // para_sep - paragraph separator (e.g. "\n\n") // // For a TEXT modality the render composes these markers around the surface that // the EXISTING realizer produces (realize_lang / sem_realize). For a non-text // modality (audio/image) the profile declares modality + media_type and the // render dispatches to the medium projector, which reads the SAME frame's // geometry (its intent/affect/structure) and projects it onto sound or pixels — // deterministic-from-meaning, nothing invented. That dispatch point is where a // music profile or image profile conforms, native, no parallel layer. // -- Constructor ------------------------------------------------------------- fn surface_profile(surface: String, modality: String, media_type: String, head_open: String, head_close: String, emph_open: String, emph_close: String, item_mark: String, para_sep: String) -> [String] { let r: [String] = native_list_empty() let r = native_list_append(r, "surface") let r = native_list_append(r, surface) let r = native_list_append(r, "modality") let r = native_list_append(r, modality) let r = native_list_append(r, "media_type") let r = native_list_append(r, media_type) let r = native_list_append(r, "head_open") let r = native_list_append(r, head_open) let r = native_list_append(r, "head_close") let r = native_list_append(r, head_close) let r = native_list_append(r, "emph_open") let r = native_list_append(r, emph_open) let r = native_list_append(r, "emph_close") let r = native_list_append(r, emph_close) let r = native_list_append(r, "item_mark") let r = native_list_append(r, item_mark) let r = native_list_append(r, "para_sep") let r = native_list_append(r, para_sep) return r } // -- Accessor (same convention as lang_get; standalone so this is a leaf) ----- fn surface_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 "" } fn surface_is_text(profile: [String]) -> Bool { return str_eq(surface_get(profile, "modality"), "text") } // -- Built-in TEXT surface profiles ------------------------------------------ // Markdown: headings with "## ", emphasis with "*", "- " list items. fn surface_profile_markdown() -> [String] { return surface_profile("markdown", "text", "text/markdown", "## ", "", "*", "*", "- ", "\n\n") } // Plain text: no markup at all — headings become bare uppercase-free lines. fn surface_profile_plain() -> [String] { return surface_profile("plain", "text", "text/plain", "", "", "", "", " - ", "\n\n") } // HTML: block-level heading/emphasis tags. fn surface_profile_html() -> [String] { return surface_profile("html", "text", "text/html", "

", "

", "", "", "
  • ", "\n") } // docx: WordprocessingML is structural, not inline-markup; the head/emph slots // carry the run/style intent that the OOXML emitter maps to . Declared // here so docx is a first-class surface on the same seam. fn surface_profile_docx() -> [String] { return surface_profile("docx", "text", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Heading2:", "", "b:", "", "bullet:", "\n") } // -- Built-in NON-TEXT surface profiles (the multimodal seam) ---------------- // Symbolic music (MIDI): modality=audio. The render dispatches to the music // projector, which reads the SAME frame's intent/affect and projects it to // pitch/rhythm — deterministic-from-meaning. head/emph slots are empty because // the medium is not textual; media_type names the surface. A music profile // (scale/mode/instrument) is layered onto this by the audio agent, native. fn surface_profile_midi() -> [String] { return surface_profile("midi", "audio", "audio/midi", "", "", "", "", "", "") } // Synthesized audio (WAV): modality=audio, peer to midi. The richer audio // surface — the render SUPERPOSES ingested tonal primitives (sine at f0*n per an // ingested instrument signature) into PCM, own-core, exactly as midi writes an // SMF via struct. A music profile (scale/mode/instrument/adsr) layers onto this // as its own [String] slot-map read by the same getter. Same frame -> midi OR // audio, interchangeable; this is the audio agent's native conforming point. fn surface_profile_audio() -> [String] { return surface_profile("audio", "audio", "audio/wav", "", "", "", "", "", "") } // Image (raster): modality=image. Documented seam — the render dispatches to the // image projector, the efferent twin of image ingest, reading the same frame. fn surface_profile_image() -> [String] { return surface_profile("image", "image", "image/png", "", "", "", "", "", "") } // -- Composition helpers: wrap realized TEXT with the surface's markers ------- // // These take text the EXISTING realizer already produced and shape it for the // surface. They add NO content — pure surface typography over faithful text, // exactly as the language profile adds no content, only linguistic form. fn surface_heading(profile: [String], text: String) -> String { let o: String = surface_get(profile, "head_open") let c: String = surface_get(profile, "head_close") return o + text + c } fn surface_emph(profile: [String], text: String) -> String { let o: String = surface_get(profile, "emph_open") let c: String = surface_get(profile, "emph_close") return o + text + c } // A section: a heading + a paragraph separator + the (already realized) body. fn surface_section(profile: [String], heading: String, body: String) -> String { let sep: String = surface_get(profile, "para_sep") return surface_heading(profile, heading) + sep + body }