Skip to main content

dialect

Attribute Macro dialect 

#[dialect]
Expand description

Declare instructions with retained syntax operands and capability-based lowering.

Available with typed-declarations. The framework dependency is discovered automatically, including renamed dependencies. To use a module reexporting the framework API, apply #[vihaco(crate = path)] to the dialect module. The path is resolved in the annotated module’s parent scope; self, super, crate, and absolute paths are supported. Operand types retain their authored scope. Unannotated bindings use the corresponding field’s parser. $0:SyntaxType retains another Parse type. If it differs from the field, the generated instruction has a phase parameter defaulting to Runtime, and its Syntax form requires an instruction-owned Lower implementation. Unchanged instructions remain nongeneric and receive identity lowering. Write authored lowering implementations outside the dialect module, beside its declaration or in a separate module in the same crate.

use vihaco_runtime::dialect;

mod framework {
    pub use vihaco_runtime::*;
}

#[dialect]
#[vihaco(crate = crate::framework)]
pub mod arithmetic {
    #[instruction]
    pub struct Add(pub i64);
}

fn main() {
    use framework::{Parse, chumsky::Parser};
    assert_eq!(arithmetic::Add::parser().parse("add 2")
        .into_result().unwrap().0, 2);
}

Differing operand types are retained until explicit lowering, even when Rust already provides a conversion between them:

use vihaco_runtime::{dialect, Lower, Parse, Syntax, chumsky::Parser};
#[dialect]
mod control {
    #[instruction]
    #[pattern = "'call $0:u64"]
    pub struct Call(pub u32);
}
impl<C: ?Sized> Lower<C> for control::Call<Syntax> {
    type Runtime = control::Call;
    fn lower(self, _: &mut C) -> vihaco_runtime::eyre::Result<Self::Runtime> {
        Ok(control::Call(self.0.try_into()?))
    }
}
let source = control::Call::<Syntax>::parser().parse("call 4294967296")
    .into_result().unwrap();
assert_eq!(source.0, 4294967296);
assert!(source.lower(&mut ()).is_err());

Declare public runtime instructions and their direct parsers.

The framework root is discovered automatically from a dependency on vihaco or vihaco-runtime, including renamed dependencies. Apply #[vihaco(crate = path)] to the dialect module to select an explicit root. The path must name a module exposing the framework API and is resolved in the annotated module’s parent scope. Relative self and super paths are supported. Operand types retain their authored scope.