Skip to main content

Multi and Omni

File: quilt/src/multi.rs, quilt/src/langs/omni.rs

Multi<LS, MS>

Multi is the engine that combines a Languages registry with a MetaLanguages registry. All parsing and expansion goes through Multi.

pub struct Multi<LS: Languages, MS: MetaLanguages> {
pub langs: LS,
pub metas: MS,
}

Languages and MetaLanguages

pub trait Languages {
type Language: Language + ?Sized;
fn get(&self, lang: &str) -> Result<&Self::Language>;
fn get_mut(&mut self, lang: &str) -> Result<&mut Self::Language>;
}

pub trait MetaLanguages {
type MetaLanguage: MetaLanguage + ?Sized;
fn get(&self, lang: &str) -> Result<&Self::MetaLanguage>;
fn get_mut(&mut self, lang: &str) -> Result<&mut Self::MetaLanguage>;
}

The key entry points on Multi:

MethodDescription
parse(s)Parse s in the default language ("rs")
parse_lang(lang, s)Parse s as a single-language source
parse_chain(chain, s)Parse with a language chain (ground + defaults for bare quotes)
expand(qterm)Expand in the default language
expand_lang(lang, qterm)Expand using lang's MetaLanguage

Built-in registry types

Three concrete Languages/MetaLanguages implementations are provided:

TypeDescription
DictLanguagesBTreeMap<Box<str>, Box<dyn Language<…>>> — dynamic, heap-allocated
DictMetaLanguagesBTreeMap<Box<str>, Box<dyn MetaLanguage>>
Singleton<T>Single language; get(any_key) always returns it

DictMulti = Multi<DictLanguages, DictMetaLanguages> is the fully-dynamic version; useful when building a custom registry at runtime.


Omni

Omni = Multi<OmniLanguages, OmniMetaLanguages> is the production multi used by the CLI. It avoids Box<dyn …> allocations by using enum dispatch over all enabled languages.

pub type Omni = Multi<OmniLanguages, OmniMetaLanguages>;

OmniLanguages holds one field per language, e.g.:

pub struct OmniLanguages {
html: OmniLanguage, // OmniLanguage::Html(HtmlLanguage)
py: OmniLanguage, // OmniLanguage::Python(PythonLanguage)
rs: OmniLanguage, // OmniLanguage::Rust(RustLanguage)
txt: OmniLanguage,
wgsl: OmniLanguage,
}

OmniMetaLanguages holds only the languages that have meta-language support:

pub struct OmniMetaLanguages {
py: OmniMetaLanguage, // OmniMetaLanguage::Python(PythonMetaLanguage)
rs: OmniMetaLanguage, // OmniMetaLanguage::Rust(RustMetaLanguage)
}

Because Omni is the default, Omni::default() is the canonical way to create the engine in application code.

DynOmni

A DictMulti-based version with Box<dyn …> is also available via dict_omni_language() — useful when the language set needs to change at runtime or when compiling code that can't use enum dispatch.


Language lookup

Language names are looked up by short string key. Both short and long forms are accepted:

KeyLanguage
"rs" or "rust"Rust
"py" or "python"Python
"txt" or "text"Text
"wgsl"WGSL
"html"HTML

Only "rs" and "py" have meta-language entries; the others are parsing targets only.


The Stage and Expander

The inner Expander struct (private to multi.rs) holds a reference to the Languages registry and the current ground MetaLanguage, and implements the recursive expand method.

Stage tracks quasi-quote depth:

pub enum Stage {
Ground,
Sky(Box<str>, Index), // Sky(lang, depth)
}

The invariant: Sky(lang, d) with d > 0. An Unquote { index } with index == d escapes to Ground; one with index < d stays in Sky but at reduced depth.


The Singleton adapter

pub type Single<L, M> = Multi<Singleton<L>, Singleton<M>>;

Singleton<T> implements Languages (or MetaLanguages) by ignoring the language key and always returning the single wrapped value. Useful in tests and the bootstrap pipeline where only one language is in play.