Quick Start
Vihaco uses Rust edition 2024. Add the crates you need from the source repository. The vihaco facade re-exports the component and runtime macros.
A first component
Section titled “A first component”A component declares state and instructions with component!. The #[dispatch(...)] implementation executes each instruction and returns effects. This is the complete example from upstream:
use eyre::Result;use vihaco::{ component, dispatch, Effects, GeneratedComponent, Message, expect_exactly_one_effect,};
component! { #[derive(Debug, Default)] pub component Counter { value: i64, }
instruction { Add(i64), Print, }}
use counter::runtime::Instruction as CounterInst;
#[derive(Debug, Clone, Message)]pub struct Prefix(pub String);
#[derive(Debug, Clone, PartialEq)]pub struct Line(pub String);
#[dispatch(instruction = counter::runtime::Instruction, message = Prefix, effect = Line)]impl counter::Counter { fn execute(&mut self, inst: &CounterInst, msg: Prefix) -> Result<Effects<Line>> { match inst { CounterInst::Add(v) => { self.value += v; Ok(Effects::none()) } CounterInst::Print => Ok(Effects::one(Line(format!("{}{}", msg.0, self.value)))), } }}
fn main() -> Result<()> { let mut counter = counter::Counter::default();
// `Add` ignores its message and returns no effects. counter.execute_generated(&CounterInst::Add(2), Prefix(String::new()))?; counter.execute_generated(&CounterInst::Add(3), Prefix(String::new()))?;
// `Print` returns exactly one `Line` effect. let effects = counter.execute_generated(&CounterInst::Print, Prefix("total = ".into()))?; let line = expect_exactly_one_effect(effects)?; assert_eq!(line, Line("total = 5".into())); Ok(())}Parsing source text
Section titled “Parsing source text”The parser derive turns a surface instruction into syntax that can be parsed and resolved. The upstream example is:
use chumsky::Parser as _;use vihaco::Instruction;use vihaco_parser::Parse;
// The same enum can derive both `Instruction` (bytecode + runtime) and// `Parse` (SST). The two derives are orthogonal.#[derive(Debug, Clone, PartialEq, Instruction, vihaco_parser_derive::Parse)]#[syntax_class(instruction, head = "counter")]pub enum CounterInst { #[pattern = "'add $0"] Add(i64), Print,}
fn main() { // The syntax class supplies the `counter::` namespace. Patterns bind // source operands directly to Rust fields. let inst = CounterInst::parser() .parse("counter.add 5") .into_result() .unwrap(); assert_eq!(inst, CounterInst::Add(5));}Continue with the tutorials for instructions, messages, components, observers, and composites, or browse the generated Rust API.